diff --git a/TMessagesProj/src/main/assets/darkblue.attheme b/TMessagesProj/src/main/assets/darkblue.attheme index c533d7471..bb945993a 100644 --- a/TMessagesProj/src/main/assets/darkblue.attheme +++ b/TMessagesProj/src/main/assets/darkblue.attheme @@ -429,4 +429,11 @@ chat_searchPanelText=-8796932 chat_inContactIcon=-1 code_comment=-2130706433 chat_outCodeBackground=857487708 -chat_inCodeBackground=856033549 \ No newline at end of file +chat_inCodeBackground=856033549 +code_keyword=-27776 +code_constant=-27776 +code_function=-27776 +code_string=-7806088 +code_operator=2147483647 +code_number=-10887465 +code_comment=2147483647 \ No newline at end of file diff --git a/TMessagesProj/src/main/assets/fonts/rmono.ttf b/TMessagesProj/src/main/assets/fonts/rmono.ttf old mode 100755 new mode 100644 index b158a334e..6df2b2536 Binary files a/TMessagesProj/src/main/assets/fonts/rmono.ttf and b/TMessagesProj/src/main/assets/fonts/rmono.ttf differ diff --git a/TMessagesProj/src/main/assets/night.attheme b/TMessagesProj/src/main/assets/night.attheme index 252f7771c..4e2cdb2b0 100644 --- a/TMessagesProj/src/main/assets/night.attheme +++ b/TMessagesProj/src/main/assets/night.attheme @@ -454,4 +454,11 @@ chat_searchPanelText=-10767620 chat_inContactIcon=-1 code_comment=-2130706433 chat_outCodeBackground=859062986 -chat_inCodeBackground=855638016 \ No newline at end of file +chat_inCodeBackground=855638016 +code_keyword=-27776 +code_constant=-27776 +code_function=-27776 +code_string=-7806088 +code_operator=2147483647 +code_number=-10887465 +code_comment=2147483647 \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index 7830f3552..bd3393cde 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -515,6 +515,35 @@ public class AndroidUtilities { return spannableStringBuilder; } + public static SpannableStringBuilder replaceSingleLink(String str, int color) { + int startIndex = str.indexOf("**"); + int endIndex = str.indexOf("**", startIndex + 1); + str = str.replace("**", ""); + int index = -1; + int len = 0; + if (startIndex >= 0 && endIndex >= 0 && endIndex - startIndex > 2) { + len = endIndex - startIndex - 2; + index = startIndex; + } + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(str); + if (index >= 0) { + spannableStringBuilder.setSpan(new ClickableSpan() { + @Override + public void updateDrawState(@NonNull TextPaint ds) { + super.updateDrawState(ds); + ds.setUnderlineText(false); + ds.setColor(color); + } + + @Override + public void onClick(@NonNull View view) { + + } + }, index, index + len, 0); + } + return spannableStringBuilder; + } + public static void recycleBitmaps(List bitmapToRecycle) { if (Build.VERSION.SDK_INT <= 23) { // cause to crash: @@ -2941,6 +2970,9 @@ public class AndroidUtilities { } public static void shakeViewSpring(View view, float shiftDp, Runnable endCallback) { + if (view == null) { + return; + } int shift = dp(shiftDp); if (view.getTag(R.id.spring_tag) != null) { ((SpringAnimation) view.getTag(R.id.spring_tag)).cancel(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index aac11e4b3..a7fab26c7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -24,8 +24,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 = 4075; - public static String BUILD_VERSION_STRING = "10.2.3"; + public static int BUILD_VERSION = 4082; + public static String BUILD_VERSION_STRING = "10.2.6"; public static int APP_ID = 4; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/CodeHighlighting.java b/TMessagesProj/src/main/java/org/telegram/messenger/CodeHighlighting.java index 084b1eac6..6d1db0156 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/CodeHighlighting.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/CodeHighlighting.java @@ -1,9 +1,13 @@ package org.telegram.messenger; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.content.Context; +import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Typeface; import android.text.Editable; +import android.text.Layout; import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; @@ -12,6 +16,7 @@ import android.text.SpannedString; import android.text.TextPaint; import android.text.TextUtils; import android.text.style.CharacterStyle; +import android.text.style.LeadingMarginSpan; import android.text.style.LineHeightSpan; import android.text.style.MetricAffectingSpan; import android.util.Log; @@ -52,7 +57,13 @@ public class CodeHighlighting { public static final int MATCH_COMMENT = 6; public static final int MATCH_FUNCTION = 7; - public static class Span extends MetricAffectingSpan { + public static int getTextSizeDecrement(int codeLength) { + if (codeLength > 120) return 5; + if (codeLength > 50) return 3; + return 2; + } + + public static class Span extends CharacterStyle { public final String lng; public final String code; @@ -67,36 +78,15 @@ public class CodeHighlighting { this.lng = lng; this.code = code; - if (code == null) { - this.decrementSize = 2; - } else if (code.length() > 120) { - this.decrementSize = 5; - } else if (code.length() > 50) { - this.decrementSize = 3; - } else { - this.decrementSize = 2; - } + this.decrementSize = getTextSizeDecrement(code == null ? 0 : code.length()); this.currentType = type; this.style = style; } - @Override - public void updateMeasureState(TextPaint p) { - if (smallerSize) { - p.setTextSize(AndroidUtilities.dp(SharedConfig.fontSize - decrementSize)); - } - p.setFlags(p.getFlags() | Paint.SUBPIXEL_TEXT_FLAG); - if (style != null) { - style.applyStyle(p); - } else { - p.setTypeface(Typeface.MONOSPACE); - } - } - @Override public void updateDrawState(TextPaint p) { if (smallerSize) { - p.setTextSize(AndroidUtilities.dp(SharedConfig.fontSize - decrementSize)); + p.setTextSize(dp(SharedConfig.fontSize - decrementSize)); } if (currentType == 2) { p.setColor(0xffffffff); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java index 1bf6c8537..2945860ea 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java @@ -1384,6 +1384,14 @@ public class DatabaseMigrationHelper { version = 135; } + if (version == 135) { +// database.executeFast("DROP TABLE stickersets").stepThis().dispose(); + database.executeFast("CREATE TABLE stickersets2(id INTEGER PRIMATE KEY, data BLOB, hash INTEGER, date INTEGER);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS stickersets2_id_index ON stickersets2(id);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 136").stepThis().dispose(); + version = 136; + } + return version; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index a6e3b6ee8..8d16ba57c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -170,7 +170,7 @@ public class FileLog { //exclude file loading excludeRequests = new HashSet<>(); excludeRequests.add("TL_upload_getFile"); - excludeRequests.add("TL_upload_a"); + excludeRequests.add("TL_upload_getWebFile"); ExclusionStrategy strategy = new ExclusionStrategy() { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index 6df4e1ba4..bce7adc6b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -1244,19 +1244,36 @@ public class MediaDataController extends BaseController { return null; } + private boolean cleanedupStickerSetCache; + private void cleanupStickerSetCache() { + if (cleanedupStickerSetCache) { + return; + } + cleanedupStickerSetCache = true; + getMessagesStorage().getStorageQueue().postRunnable(() -> { + try { + final long minDate = (System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 7); + getMessagesStorage().getDatabase().executeFast("DELETE FROM stickersets2 WHERE date < " + minDate).stepThis().dispose(); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + private void saveStickerSetIntoCache(TLRPC.TL_messages_stickerSet set) { if (set == null || set.set == null) { return; } getMessagesStorage().getStorageQueue().postRunnable(() -> { try { - SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO stickersets VALUES(?, ?, ?)"); + SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO stickersets2 VALUES(?, ?, ?, ?)"); state.requery(); NativeByteBuffer data = new NativeByteBuffer(set.getObjectSize()); set.serializeToStream(data); state.bindLong(1, set.set.id); state.bindByteBuffer(2, data); state.bindInteger(3, set.set.hash); + state.bindLong(4, System.currentTimeMillis()); state.step(); data.reuse(); state.dispose(); @@ -1264,6 +1281,7 @@ public class MediaDataController extends BaseController { FileLog.e(e); } }); + cleanupStickerSetCache(); } private TLRPC.TL_messages_stickerSet getCachedStickerSetInternal(long id, Integer hash) { @@ -1271,7 +1289,7 @@ public class MediaDataController extends BaseController { SQLiteCursor cursor = null; NativeByteBuffer data = null; try { - cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT data, hash FROM stickersets WHERE id = " + id + " LIMIT 1"); + cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT data, hash FROM stickersets2 WHERE id = " + id + " LIMIT 1"); if (cursor.next() && !cursor.isNull(0)) { data = cursor.byteBufferValue(0); if (data != null) { @@ -6283,11 +6301,15 @@ public class MediaDataController extends BaseController { content = substring(content, 0, content.length() - 1); } if (!TextUtils.isEmpty(content)) { + if (content.length() > 1 && content.charAt(0) == '\n') { + content = content.subSequence(1, content.length()); + index--; + } message[0] = AndroidUtilities.concat(startMessage, content, endMessage); TLRPC.TL_messageEntityPre entity = new TLRPC.TL_messageEntityPre(); entity.offset = start + (replacedFirst ? 0 : 1); entity.length = index - start - 3 - (language.length() + (!language.isEmpty() ? 1 : 0)) + (replacedFirst ? 0 : 1); - entity.language = language; + entity.language = TextUtils.isEmpty(language) || language.trim().length() == 0 ? "" : language; entities.add(entity); lastIndex -= 6; } @@ -6630,10 +6652,13 @@ public class MediaDataController extends BaseController { TLRPC.Peer peer2 = getMessagesController().getPeer(dialogId); TLRPC.Peer thisPeer = quote.message.messageOwner.peer_id; if (peer2 != null && !MessageObject.peersEqual(peer2, thisPeer)) { - draftMessage.reply_to.flags |= 1; - draftMessage.reply_to.reply_to_peer_id = getMessagesController().getInputPeer(peer2); + draftMessage.reply_to.flags |= 2; + draftMessage.reply_to.reply_to_peer_id = getMessagesController().getInputPeer(thisPeer); } } + } else if (dialogId != MessageObject.getDialogId(replyToMessage)) { + draftMessage.reply_to.flags |= 2; + draftMessage.reply_to.reply_to_peer_id = getMessagesController().getInputPeer(getMessagesController().getPeer(MessageObject.getDialogId(replyToMessage))); } } if (entities != null && !entities.isEmpty()) { @@ -6644,10 +6669,20 @@ public class MediaDataController extends BaseController { SparseArray threads = drafts.get(dialogId); TLRPC.DraftMessage currentDraft = threads == null ? null : threads.get(threadId); if (!clean) { - if ( - currentDraft != null && currentDraft.message.equals(draftMessage.message) && replyToEquals(currentDraft.reply_to, draftMessage.reply_to) && currentDraft.no_webpage == draftMessage.no_webpage || - currentDraft == null && TextUtils.isEmpty(draftMessage.message) && (draftMessage.reply_to == null || draftMessage.reply_to.reply_to_msg_id == 0) - ) { + boolean sameDraft; + if (currentDraft != null) { + sameDraft = ( + currentDraft.message.equals(draftMessage.message) && + replyToEquals(currentDraft.reply_to, draftMessage.reply_to) && + currentDraft.no_webpage == draftMessage.no_webpage + ); + } else { + sameDraft = ( + TextUtils.isEmpty(draftMessage.message) && + (draftMessage.reply_to == null || draftMessage.reply_to.reply_to_msg_id == 0) + ); + } + if (sameDraft) { return; } } @@ -6791,7 +6826,7 @@ public class MediaDataController extends BaseController { if (threads != null) { replyToMessage = threads.get(threadId); } - if (replyToMessage == null || replyToMessage.id != draft.reply_to.reply_to_msg_id || !MessageObject.peersEqual(replyToMessage.peer_id, getMessagesController().getPeer(draft.reply_to.reply_to_msg_id))) { + if (replyToMessage == null || replyToMessage.id != draft.reply_to.reply_to_msg_id || !MessageObject.peersEqual(draft.reply_to.reply_to_peer_id, replyToMessage.peer_id)) { replyToMessage = null; } } else if (draft != null && draft.reply_to == null) { @@ -6823,13 +6858,14 @@ public class MediaDataController extends BaseController { } editor.commit(); if (fromServer && (threadId == 0 || getMessagesController().isForum(dialogId))) { - if (draft != null && draft.reply_to != null && draft.reply_to.reply_to_msg_id != 0 && replyToMessage == null) { + if (draft != null && draft.reply_to != null && draft.reply_to.reply_to_msg_id != 0 && (replyToMessage == null || replyToMessage.reply_to instanceof TLRPC.TL_messageReplyHeader && replyToMessage.replyMessage == null)) { + final long replyDialogId = (draft.reply_to.flags & 2) != 0 ? DialogObject.getPeerDialogId(draft.reply_to.reply_to_peer_id) : dialogId; TLRPC.User user = null; TLRPC.Chat chat = null; - if (DialogObject.isUserDialog(dialogId)) { - user = getMessagesController().getUser(dialogId); + if (DialogObject.isUserDialog(replyDialogId)) { + user = getMessagesController().getUser(replyDialogId); } else { - chat = getMessagesController().getChat(-dialogId); + chat = getMessagesController().getChat(-replyDialogId); } if (user != null || chat != null) { long channelId = ChatObject.isChannel(chat) ? chat.id : 0; @@ -6838,7 +6874,7 @@ public class MediaDataController extends BaseController { getMessagesStorage().getStorageQueue().postRunnable(() -> { try { TLRPC.Message message = null; - SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data FROM messages_v2 WHERE mid = %d and uid = %d", messageId, dialogId)); + SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, replydata FROM messages_v2 WHERE mid = %d and uid = %d", messageId, replyDialogId)); if (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { @@ -6846,6 +6882,33 @@ public class MediaDataController extends BaseController { message.readAttachPath(data, getUserConfig().clientUserId); data.reuse(); } + if (message != null) { + ArrayList usersToLoad = new ArrayList<>(); + ArrayList chatsToLoad = new ArrayList<>(); + LongSparseArray>> replyMessageOwners = new LongSparseArray<>(); + LongSparseArray> dialogReplyMessagesIds = new LongSparseArray<>(); + try { + if (message.reply_to != null && message.reply_to.reply_to_msg_id != 0) { + if (!cursor.isNull(1)) { + NativeByteBuffer data2 = cursor.byteBufferValue(1); + if (data2 != null) { + message.replyMessage = TLRPC.Message.TLdeserialize(data2, data2.readInt32(false), false); + message.replyMessage.readAttachPath(data2, getUserConfig().clientUserId); + data2.reuse(); + if (message.replyMessage != null) { + MessagesStorage.addUsersAndChatsFromMessage(message.replyMessage, usersToLoad, chatsToLoad, null); + } + } + } + if (message.replyMessage == null) { + MessagesStorage.addReplyMessages(message, replyMessageOwners, dialogReplyMessagesIds); + } + } + } catch (Exception e) { + getMessagesStorage().checkSQLException(e); + } + getMessagesStorage().loadReplyMessages(replyMessageOwners, dialogReplyMessagesIds, usersToLoad, chatsToLoad, false); + } } cursor.dispose(); if (message == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index b4a4aa0e6..ea2f5d361 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -10,9 +10,10 @@ package org.telegram.messenger; import static org.telegram.messenger.AndroidUtilities.dp; +import android.graphics.Canvas; import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Rect; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; @@ -32,10 +33,10 @@ import android.text.style.ClickableSpan; import android.text.style.URLSpan; import android.text.util.Linkify; import android.util.Base64; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; +import androidx.core.graphics.ColorUtils; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.browser.Browser; @@ -56,6 +57,7 @@ import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.QuoteSpan; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.Reactions.ReactionsUtils; +import org.telegram.ui.Components.Text; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.TranscribeButton; import org.telegram.ui.Components.TypefaceSpan; @@ -675,6 +677,152 @@ public class MessageObject { public boolean code; public boolean quote; + public String language; + public Text languageLayout; + public int languageHeight; // included in padTop + + public boolean hasCodeCopyButton; + public int copyIconColor; + public Drawable copyIcon; + public Text copyText; + public int copySelectorColor; + public Drawable copySelector; + public Paint copySeparator; + + public void layoutCode(String lng, int codeLength) { + hasCodeCopyButton = codeLength >= 75; + if (hasCodeCopyButton) { + copyText = new Text(LocaleController.getString(R.string.CopyCode).toUpperCase(), SharedConfig.fontSize - 3, AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + copyIcon = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.msg_copy).mutate(); + copyIcon.setColorFilter(new PorterDuffColorFilter(copyIconColor, PorterDuff.Mode.SRC_IN)); + copySelector = Theme.createRadSelectorDrawable(copySelectorColor, 0, 0, Math.min(5, SharedConfig.bubbleRadius), 0); + copySeparator = new Paint(Paint.ANTI_ALIAS_FLAG); + } + if (TextUtils.isEmpty(lng)) { + language = null; + languageLayout = null; + return; + } + language = lng; + languageLayout = new Text( + capitalizeLanguage(lng), + SharedConfig.fontSize - 1 - CodeHighlighting.getTextSizeDecrement(codeLength) / 2, + AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM) + ); + languageHeight = (int) (languageLayout.getTextSize() * 1.714f) + dp(4); + } + + public void drawCopyCodeButton(Canvas canvas, RectF bounds, int textColor, int backgroundColor, float alpha) { + if (!hasCodeCopyButton) { + return; + } + + final int selectorColor = Theme.multAlpha(textColor, .10f); + if (copySelectorColor != selectorColor) { + Theme.setSelectorDrawableColor(copySelector, copySelectorColor = selectorColor, true); + } + copySelector.setBounds((int) bounds.left + dp(3), (int) (bounds.bottom - dp(38)), (int) bounds.right, (int) bounds.bottom); + copySelector.setAlpha((int) (0xFF * alpha)); + copySelector.draw(canvas); + + copySeparator.setColor(ColorUtils.setAlphaComponent(backgroundColor, 0x26)); + canvas.drawRect(bounds.left + dp(10), bounds.bottom - dp(38) - AndroidUtilities.getShadowHeight(), bounds.right - dp(6.66f), bounds.bottom - dp(38), copySeparator); + + final float iconScale = .8f; + final float contentWidth = Math.min(bounds.width() - dp(12), copyIcon.getIntrinsicWidth() * iconScale + dp(5) + copyText.getCurrentWidth()); + float x = bounds.centerX() - contentWidth / 2f; + final float cy = bounds.bottom - dp(38) / 2f; + + if (copyIconColor != textColor) { + copyIcon.setColorFilter(new PorterDuffColorFilter(copyIconColor = textColor, PorterDuff.Mode.SRC_IN)); + } + copyIcon.setAlpha((int) (0xFF * alpha)); + copyIcon.setBounds( + (int) x, + (int) (cy - copyIcon.getIntrinsicHeight() * iconScale / 2f), + (int) (x + copyIcon.getIntrinsicWidth() * iconScale), + (int) (cy + copyIcon.getIntrinsicHeight() * iconScale / 2f) + ); + copyIcon.draw(canvas); + + x += copyIcon.getIntrinsicWidth() * iconScale + dp(5); + copyText + .ellipsize((int) (contentWidth - (copyIcon.getIntrinsicWidth() * iconScale + dp(5))) + dp(12)) + .draw(canvas, x, cy, textColor, alpha); + } + + private static String capitalizeLanguage(String lng) { + if (lng == null) return null; + String llng = lng.toLowerCase().replaceAll("\\W", ""); + switch (llng) { + case "js": + case "javascript": + return "JavaScript"; + case "ts": + case "typescript": + return "TypeScript"; + case "objc": + case "objectivec": + return "Objective-C"; + case "md": + case "markdown": + return "Markdown"; + case "rb": + case "ruby": + return "Ruby"; + case "py": + case "python": + return "Python"; + case "actionscript": return "ActionScript"; + case "autohotkey": return "AutoHotKey"; + case "cpp": return "C++"; + case "csharp": + case "cs": + return "C#"; + case "aspnet": return "ASP.NET"; + case "c": + case "arduino": + case "swift": + case "rust": + case "pascal": + case "kotlin": + case "lua": + case "docker": + case "dockerfile": + case "dart": + case "java": + return capitalizeFirst(lng); + case "http": + case "html": + case "css": + case "scss": + case "less": + case "asm": + case "nasm": + case "wasm": + case "xml": + case "yaml": + case "yml": + case "php": + case "json": + case "json5": + case "r": + case "ini": + case "glsl": + case "hlsl": + case "csv": + case "cobol": + case "jsx": + case "tsx": + return lng.toUpperCase(); + } + return lng; + } + + private static String capitalizeFirst(String str) { + return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase(); + } + public boolean isRtl() { return (directionFlags & FLAG_RTL) != 0 && (directionFlags & FLAG_NOT_RTL) == 0; } @@ -1249,6 +1397,7 @@ public class MessageObject { public boolean hasCodeAtTop, hasCodeAtBottom; public boolean hasQuote; public boolean hasSingleQuote; + public boolean hasSingleCode; public boolean hasQuoteAtBottom; public MessageObject(int accountNum, TL_stories.StoryItem storyItem) { @@ -5777,7 +5926,7 @@ public class MessageObject { } generatedWithDensity = AndroidUtilities.density; if (hasCode) { - maxWidth = generatedWithMinSize - dp(45); + maxWidth = generatedWithMinSize - dp(45 + 15); if (needDrawAvatarInternal() && !isOutOwner() && !messageOwner.isThreadMessage) { maxWidth -= dp(52); } @@ -5802,7 +5951,7 @@ public class MessageObject { maxWidth -= dp(52); } if (needDrawShareButton() && !isOutOwner()) { - maxWidth -= dp(20); + maxWidth -= dp(10); } if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) { maxWidth -= dp(10); @@ -5894,6 +6043,7 @@ public class MessageObject { hasCode = messageText instanceof Spanned && ((Spanned) messageText).getSpans(0, messageText.length(), CodeHighlighting.Span.class).length > 0; hasQuote = messageText instanceof Spanned && ((Spanned) messageText).getSpans(0, messageText.length(), QuoteSpan.QuoteStyleSpan.class).length > 0; hasSingleQuote = false; + hasSingleCode = false; if (messageText instanceof Spanned) { Spanned spanned = (Spanned) messageText; @@ -5902,6 +6052,9 @@ public class MessageObject { quoteSpans[i].adaptLineHeight = false; } hasSingleQuote = quoteSpans.length == 1 && spanned.getSpanStart(quoteSpans[0]) == 0 && spanned.getSpanEnd(quoteSpans[0]) == spanned.length(); + + CodeHighlighting.Span[] codeSpans = spanned.getSpans(0, spanned.length(), CodeHighlighting.Span.class); + hasSingleCode = codeSpans.length == 1 && spanned.getSpanStart(codeSpans[0]) == 0 && spanned.getSpanEnd(codeSpans[0]) == spanned.length(); } @@ -5909,6 +6062,8 @@ public class MessageObject { if (hasSingleQuote) { maxWidth -= AndroidUtilities.dp(32); + } else if (hasSingleCode) { + maxWidth -= AndroidUtilities.dp(15); } StaticLayout textLayout; @@ -5948,6 +6103,8 @@ public class MessageObject { if (hasSingleQuote) { maxWidth += AndroidUtilities.dp(32); + } else if (hasSingleCode) { + maxWidth += AndroidUtilities.dp(15); } textHeight = 0; @@ -5996,6 +6153,7 @@ public class MessageObject { hasCodeAtBottom = false; hasQuoteAtBottom = false; hasSingleQuote = false; + hasSingleCode = false; float offset = 0; for (int a = 0; a < textRanges.size(); a++) { TextLayoutBlock block = new TextLayoutBlock(); @@ -6016,17 +6174,19 @@ public class MessageObject { hasCodeAtBottom = block.code; } hasSingleQuote = block.first && block.last && block.quote; + hasSingleCode = block.first && block.last && !block.quote && block.code; if (block.quote) { if (block.first && block.last) { - block.padTop = block.padBottom = AndroidUtilities.dp(6); + block.padTop = block.padBottom = dp(6); } else { - block.padTop = AndroidUtilities.dp(block.first ? 8 : 6); - block.padBottom = AndroidUtilities.dp(7); + block.padTop = dp(block.first ? 8 : 6); + block.padBottom = dp(7); } } else if (block.code) { - block.padTop = block.first ? 0 : AndroidUtilities.dp(5); - block.padBottom = block.last ? 0 : AndroidUtilities.dp(5); + block.layoutCode(range.language, range.end - range.start); + block.padTop = dp(4) + block.languageHeight + (block.first ? 0 : dp(5)); + block.padBottom = dp(4) + (block.last ? 0 : dp(7)) + (block.hasCodeCopyButton ? dp(38) : 0); } TextPaint layoutPaint = paint; @@ -6042,12 +6202,23 @@ public class MessageObject { } CharSequence blockText = messageText.subSequence(range.start, range.end); + int blockMaxWidth = maxWidth; + if (block.quote) { + blockMaxWidth -= dp(24); + } else if (block.code) { + blockMaxWidth -= dp(15); + } if (blocksCount == 1) { - if (block.code && !block.quote && textLayout.getText() instanceof Spannable && !TextUtils.isEmpty(range.language)) { - SpannableString sb = CodeHighlighting.getHighlighted(blockText.toString(), range.language); - if (hasUrls && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (block.code && !block.quote && textLayout.getText() instanceof Spannable) { + SpannableString sb; + if (!TextUtils.isEmpty(range.language)) { + sb = CodeHighlighting.getHighlighted(blockText.toString(), range.language); + } else { + sb = new SpannableString(blockText.toString()); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { StaticLayout.Builder builder = - StaticLayout.Builder.obtain(sb, 0, sb.length(), layoutPaint, maxWidth - (block.quote ? dp(24) : 0) + dp(2)) + StaticLayout.Builder.obtain(sb, 0, sb.length(), layoutPaint, blockMaxWidth) .setLineSpacing(lineAdd, lineSpacing) .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) @@ -6060,7 +6231,7 @@ public class MessageObject { } textLayout = builder.build(); } else { - textLayout = new StaticLayout(sb, 0, sb.length(), layoutPaint, maxWidth - (block.quote ? dp(24) : 0), align, lineSpacing, lineAdd, false); + textLayout = new StaticLayout(sb, 0, sb.length(), layoutPaint, blockMaxWidth, align, lineSpacing, lineAdd, false); } } @@ -6102,22 +6273,16 @@ public class MessageObject { } else { sb = SpannableString.valueOf(blockText); } - if (hasUrls && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { StaticLayout.Builder builder = - StaticLayout.Builder.obtain(sb, 0, sb.length(), layoutPaint, maxWidth - (block.quote ? dp(24) : 0) + dp(2)) - .setLineSpacing(lineAdd, lineSpacing) - .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) - .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) - .setAlignment(align); - if (emojiOnlyCount > 0) { - builder.setIncludePad(false); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - builder.setUseLineSpacingFromFallbacks(false); - } - } + StaticLayout.Builder.obtain(sb, 0, sb.length(), layoutPaint, blockMaxWidth) + .setLineSpacing(lineAdd, lineSpacing) + .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) + .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) + .setAlignment(align); block.textLayout = builder.build(); } else { - block.textLayout = new StaticLayout(sb, 0, sb.length(), layoutPaint, maxWidth - (block.quote ? dp(24) : 0), align, lineSpacing, lineAdd, false); + block.textLayout = new StaticLayout(sb, 0, sb.length(), layoutPaint, blockMaxWidth, align, lineSpacing, lineAdd, false); } block.textYOffset = offset; @@ -6162,6 +6327,8 @@ public class MessageObject { } if (block.quote) { lastLine += AndroidUtilities.dp(32); + } else if (block.code) { + lastLine += AndroidUtilities.dp(15); } int linesMaxWidth = (int) Math.ceil(lastLine); @@ -6200,6 +6367,8 @@ public class MessageObject { if (block.quote) { lineWidth += AndroidUtilities.dp(32); + } else if (block.code) { + lineWidth += AndroidUtilities.dp(15); } try { @@ -6262,7 +6431,13 @@ public class MessageObject { block.spoilers.clear(); if (!isSpoilersRevealed && !spoiledLoginCode) { - SpoilerEffect.addSpoilers(null, block.textLayout, -1, linesMaxWidthWithLeft, null, block.spoilers); + int right = linesMaxWidthWithLeft; + if (block.quote) { + right -= AndroidUtilities.dp(32); + } else if (block.code) { + right -= AndroidUtilities.dp(15); + } + SpoilerEffect.addSpoilers(null, block.textLayout, -1, right, null, block.spoilers); } } @@ -6278,11 +6453,8 @@ public class MessageObject { public boolean hasRtl; public float textXOffset; public final ArrayList textLayoutBlocks = new ArrayList<>(); - public boolean hasCode; - public boolean hasCodeAtTop, hasCodeAtBottom; - public boolean hasQuote; - public boolean hasSingleQuote; - public boolean hasQuoteAtBottom; + public boolean hasCode, hasCodeAtTop, hasCodeAtBottom, hasSingleCode; + public boolean hasQuote, hasQuoteAtBottom, hasSingleQuote; public TextLayoutBlocks(MessageObject messageObject, @NonNull CharSequence text, TextPaint textPaint, int width) { this.text = text; @@ -6291,6 +6463,7 @@ public class MessageObject { hasCode = text instanceof Spanned && ((Spanned) text).getSpans(0, text.length(), CodeHighlighting.Span.class).length > 0; hasQuote = text instanceof Spanned && ((Spanned) text).getSpans(0, text.length(), QuoteSpan.QuoteStyleSpan.class).length > 0; hasSingleQuote = false; + hasSingleCode = false; if (text instanceof Spanned) { Spanned spanned = (Spanned) text; @@ -6299,12 +6472,17 @@ public class MessageObject { quoteSpans[i].adaptLineHeight = false; } hasSingleQuote = quoteSpans.length == 1 && spanned.getSpanStart(quoteSpans[0]) == 0 && spanned.getSpanEnd(quoteSpans[0]) == spanned.length(); + + CodeHighlighting.Span[] codeSpans = spanned.getSpans(0, spanned.length(), CodeHighlighting.Span.class); + hasSingleCode = codeSpans.length == 1 && spanned.getSpanStart(codeSpans[0]) == 0 && spanned.getSpanEnd(codeSpans[0]) == spanned.length(); } StaticLayout textLayout; if (hasSingleQuote) { width -= AndroidUtilities.dp(32); + } else if (hasSingleCode) { + width -= AndroidUtilities.dp(15); } final float lineSpacing = 1f; @@ -6329,6 +6507,8 @@ public class MessageObject { if (hasSingleQuote) { width += AndroidUtilities.dp(32); + } else if (hasSingleCode) { + width += AndroidUtilities.dp(15); } textHeight = 0; @@ -6395,14 +6575,15 @@ public class MessageObject { if (block.quote) { if (block.first && block.last) { - block.padTop = block.padBottom = AndroidUtilities.dp(6); + block.padTop = block.padBottom = dp(6); } else { - block.padTop = AndroidUtilities.dp(block.first ? 8 : 6); - block.padBottom = AndroidUtilities.dp(7); + block.padTop = dp(block.first ? 8 : 6); + block.padBottom = dp(7); } } else if (block.code) { - block.padTop = block.first ? 0 : AndroidUtilities.dp(5); - block.padBottom = block.last ? 0 : AndroidUtilities.dp(5); + block.layoutCode(range.language, range.end - range.start); + block.padTop = dp(4) + block.languageHeight + (block.first ? 0 : dp(5)); + block.padBottom = dp(4) + (block.last ? 0 : dp(7)) + (block.hasCodeCopyButton ? dp(38) : 0); } TextPaint layoutPaint = textPaint; @@ -6417,19 +6598,30 @@ public class MessageObject { } } + int blockMaxWidth = width; + if (block.quote) { + blockMaxWidth -= dp(32); + } else if (block.code) { + blockMaxWidth -= dp(15); + } if (blocksCount == 1) { - if (block.code && !block.quote && textLayout.getText() instanceof Spannable && !TextUtils.isEmpty(range.language)) { - SpannableString sb = CodeHighlighting.getHighlighted(text.subSequence(range.start, range.end).toString(), range.language); + if (block.code && !block.quote && textLayout.getText() instanceof Spannable) { + SpannableString sb; + if (!TextUtils.isEmpty(range.language)) { + sb = CodeHighlighting.getHighlighted(text.subSequence(range.start, range.end).toString(), range.language); + } else { + sb = new SpannableString(text.subSequence(range.start, range.end)); + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { StaticLayout.Builder builder = - StaticLayout.Builder.obtain(sb, 0, text.length(), layoutPaint, width) + StaticLayout.Builder.obtain(sb, 0, text.length(), layoutPaint, blockMaxWidth) .setLineSpacing(lineAdd, lineSpacing) .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) .setAlignment(align); textLayout = builder.build(); } else { - textLayout = new StaticLayout(sb, layoutPaint, width, align, lineSpacing, lineAdd, false); + textLayout = new StaticLayout(sb, layoutPaint, blockMaxWidth, align, lineSpacing, lineAdd, false); } } @@ -6455,7 +6647,7 @@ public class MessageObject { } else { sb = SpannableString.valueOf(text.subSequence(startCharacter, endCharacter)); } - block.textLayout = new StaticLayout(sb, 0, sb.length(), layoutPaint, width - (block.quote ? dp(24) : 0), align, lineSpacing, lineAdd, false); + block.textLayout = new StaticLayout(sb, 0, sb.length(), layoutPaint, blockMaxWidth, align, lineSpacing, lineAdd, false); block.textYOffset = offset; if (a != 0) { @@ -6538,6 +6730,8 @@ public class MessageObject { if (block.quote) { lineWidth += AndroidUtilities.dp(32); + } else if (block.code) { + lineWidth += AndroidUtilities.dp(15); } try { @@ -6594,14 +6788,17 @@ public class MessageObject { } textWidth = Math.max(textWidth, Math.min(width, linesMaxWidth)); -// if (block.quote && hasSingleQuote) { -// textWidth += AndroidUtilities.dp(32); -// } } linesOffset += currentBlockLinesCount; if (messageObject != null && !messageObject.isSpoilersRevealed && !messageObject.spoiledLoginCode) { - SpoilerEffect.addSpoilers(null, block.textLayout, -1, linesMaxWidthWithLeft, null, block.spoilers); + int right = linesMaxWidthWithLeft; + if (block.quote) { + right -= AndroidUtilities.dp(32); + } else if (block.code) { + right -= AndroidUtilities.dp(15); + } + SpoilerEffect.addSpoilers(null, block.textLayout, -1, right, null, block.spoilers); } } } @@ -6720,6 +6917,25 @@ public class MessageObject { return false; } + public static boolean peersEqual(TLRPC.InputPeer a, TLRPC.Peer b) { + if (a == null && b == null) { + return true; + } + if (a == null || b == null) { + return false; + } + if (a instanceof TLRPC.TL_inputPeerChat && b instanceof TLRPC.TL_peerChat) { + return a.chat_id == b.chat_id; + } + if (a instanceof TLRPC.TL_inputPeerChannel && b instanceof TLRPC.TL_peerChannel) { + return a.channel_id == b.channel_id; + } + if (a instanceof TLRPC.TL_inputPeerUser && b instanceof TLRPC.TL_peerUser) { + return a.user_id == b.user_id; + } + return false; + } + public static boolean peersEqual(TLRPC.Peer a, TLRPC.Peer b) { if (a == null && b == null) { 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 81162e31a..a73a9803f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -14757,6 +14757,9 @@ public class MessagesController extends BaseController implements NotificationCe } else { break; } + if (updates.updates.size() <= 0) { + break; + } updates.updates.remove(a); a--; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 6a38913b7..f238a4778 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -97,7 +97,7 @@ public class MessagesStorage extends BaseController { } } - public final static int LAST_DB_VERSION = 135; + public final static int LAST_DB_VERSION = 136; private boolean databaseMigrationInProgress; public boolean showClearDatabaseAlert; private LongSparseIntArray dialogIsForum = new LongSparseIntArray(); @@ -597,7 +597,6 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE TABLE stickers_v2(id INTEGER PRIMARY KEY, data BLOB, date INTEGER, hash INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE stickers_featured(id INTEGER PRIMARY KEY, data BLOB, unread BLOB, date INTEGER, hash INTEGER, premium INTEGER, emoji INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE stickers_dice(emoji TEXT PRIMARY KEY, data BLOB, date INTEGER);").stepThis().dispose(); - database.executeFast("CREATE TABLE stickersets(id INTEGER PRIMATE KEY, data BLOB, hash INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE hashtag_recent_v2(id TEXT PRIMARY KEY, date INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE webpage_pending_v2(id INTEGER, mid INTEGER, uid INTEGER, PRIMARY KEY (id, mid, uid));").stepThis().dispose(); database.executeFast("CREATE TABLE sent_files_v2(uid TEXT, type INTEGER, data BLOB, parent TEXT, PRIMARY KEY (uid, type))").stepThis().dispose(); @@ -609,6 +608,9 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE TABLE requested_holes(uid INTEGER, seq_out_start INTEGER, seq_out_end INTEGER, PRIMARY KEY (uid, seq_out_start, seq_out_end));").stepThis().dispose(); database.executeFast("CREATE TABLE sharing_locations(uid INTEGER PRIMARY KEY, mid INTEGER, date INTEGER, period INTEGER, message BLOB, proximity INTEGER);").stepThis().dispose(); + database.executeFast("CREATE TABLE stickersets2(id INTEGER PRIMATE KEY, data BLOB, hash INTEGER, date INTEGER);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS stickersets2_id_index ON stickersets2(id);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS stickers_featured_emoji_index ON stickers_featured(emoji);").stepThis().dispose(); database.executeFast("CREATE TABLE shortcut_widget(id INTEGER, did INTEGER, ord INTEGER, PRIMARY KEY (id, did));").stepThis().dispose(); @@ -1323,7 +1325,7 @@ public class MessagesStorage extends BaseController { database.executeFast("DELETE FROM attach_menu_bots").stepThis().dispose(); database.executeFast("DELETE FROM animated_emoji").stepThis().dispose(); database.executeFast("DELETE FROM stickers_v2").stepThis().dispose(); - database.executeFast("DELETE FROM stickersets").stepThis().dispose(); + database.executeFast("DELETE FROM stickersets2").stepThis().dispose(); database.executeFast("DELETE FROM messages_holes_topics").stepThis().dispose(); database.executeFast("DELETE FROM messages_topics").stepThis().dispose(); database.executeFast("DELETE FROM topics").stepThis().dispose(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/utils/CustomHtml.java b/TMessagesProj/src/main/java/org/telegram/messenger/utils/CustomHtml.java index d44d91f5a..b6cc39c6d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/utils/CustomHtml.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/utils/CustomHtml.java @@ -1,6 +1,7 @@ package org.telegram.messenger.utils; import android.text.Spanned; +import android.text.TextUtils; import org.telegram.messenger.CodeHighlighting; import org.telegram.ui.Components.AnimatedEmojiSpan; @@ -164,7 +165,11 @@ public class CustomHtml { for (int j = 0; j < spans.length; ++j) { CodeHighlighting.Span span = spans[j]; if (span != null) { - out.append("
");
+                        if (TextUtils.isEmpty(span.lng)) {
+                            out.append("
");
+                        } else {
+                            out.append("
");
+                        }
                     }
                 }
             }
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 b87533dd3..08247e705 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java
@@ -1751,9 +1751,9 @@ public class Theme {
             if (isDarkTheme && currentColors.get(key_chat_outBubbleGradient1) != 0) {
                 int outBubbleAverage = averageColor(currentColors, key_chat_outBubbleGradient1, key_chat_outBubbleGradient2, key_chat_outBubbleGradient3);
                 Color.colorToHSV(outBubbleAverage, tempHSV);
-                tempHSV[1] = Utilities.clamp(tempHSV[1] + .3f, 1, 0);
-                tempHSV[2] = Utilities.clamp(tempHSV[2] + -.4f, 1, 0);
-                currentColors.put(key_chat_outCodeBackground, Color.HSVToColor(0x70, tempHSV));
+                tempHSV[1] = Utilities.clamp(tempHSV[1] + .1f, 1, 0);
+                tempHSV[2] = Utilities.clamp(tempHSV[2] - .8f, 1, 0);
+                currentColors.put(key_chat_outCodeBackground, Color.HSVToColor(0x40, tempHSV));
             } else {
                 currentColors.put(key_chat_outCodeBackground, codeBackground(outBubble, isDarkTheme));
             }
@@ -1817,13 +1817,16 @@ public class Theme {
         private int codeBackground(int bubbleColor, boolean isDarkTheme) {
             Color.colorToHSV(bubbleColor, tempHSV);
             int alpha = 0x20;
-            if (tempHSV[1] <= 0 || tempHSV[2] >= 1 || tempHSV[2] <= 0) {
-                tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] + (isDarkTheme ? .3f : -.2f)));
+            if (isDarkTheme) {
+                alpha = 0x40;
+                tempHSV[1] = Utilities.clamp(tempHSV[1] - .08f, 1f, 0f);
+                tempHSV[2] = .03f;
             } else {
-                tempHSV[1] = Math.max(0, Math.min(1, tempHSV[1] + (isDarkTheme ? -.3f : .28f)));
-                tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] + (isDarkTheme ? +.1f : -.1f)));
-                if (isDarkTheme) {
-                    alpha = 0x60;
+                if (tempHSV[1] <= 0 || tempHSV[2] >= 1 || tempHSV[2] <= 0) {
+                    tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] + -.2f));
+                } else {
+                    tempHSV[1] = Math.max(0, Math.min(1, tempHSV[1] + .28f));
+                    tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] + -.1f));
                 }
             }
             return Color.HSVToColor(alpha, tempHSV);
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 85544e6d7..1a5b9c407 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java
@@ -34,13 +34,11 @@ import android.graphics.Path;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
-import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.graphics.Shader;
 import android.graphics.Typeface;
-import android.graphics.Xfermode;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.GradientDrawable;
@@ -61,9 +59,7 @@ import android.text.TextUtils;
 import android.text.style.CharacterStyle;
 import android.text.style.ClickableSpan;
 import android.text.style.LeadingMarginSpan;
-import android.text.style.LineHeightSpan;
 import android.text.style.URLSpan;
-import android.util.Log;
 import android.util.Property;
 import android.util.SparseArray;
 import android.util.StateSet;
@@ -127,7 +123,6 @@ import org.telegram.tgnet.ConnectionsManager;
 import org.telegram.tgnet.TLObject;
 import org.telegram.tgnet.TLRPC;
 import org.telegram.tgnet.tl.TL_stories;
-import org.telegram.ui.ActionBar.AdjustPanLayoutHelper;
 import org.telegram.ui.ActionBar.Theme;
 import org.telegram.ui.ChatActivity;
 import org.telegram.ui.Components.AnimatedEmojiDrawable;
@@ -450,6 +445,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
         default void didPressExtendedMediaPreview(ChatMessageCell cell, TLRPC.KeyboardButton button) {
         }
 
+        default void didPressUserStatus(ChatMessageCell cell, TLRPC.User user, TLRPC.Document document) {
+
+        }
+
         default void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY) {
         }
 
@@ -497,7 +496,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
         default void didPressUrl(ChatMessageCell cell, CharacterStyle url, boolean longPress) {
         }
 
-        default void didPressCode(ChatMessageCell cell, CharacterStyle span, boolean longPress) {
+        default void didPressCodeCopy(ChatMessageCell cell, MessageObject.TextLayoutBlock block) {
 
         }
 
@@ -883,6 +882,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
     private Path instantLinkArrowPath;
     private Paint instantLinkArrowPaint;
 
+    private int nameLayoutSelectorColor;
+    private Drawable nameLayoutSelector;
+    private boolean nameLayoutPressed;
+
+    private int nameStatusSelectorColor;
+    private Drawable nameStatusSelector;
+    private boolean nameStatusPressed;
+
     private RoundVideoPlayingDrawable roundVideoPlayingDrawable;
 
     private StaticLayout docTitleLayout;
@@ -955,6 +962,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
 
     private AnimatedEmojiSpan pressedEmoji;
     private LinkSpanDrawable pressedLink;
+    private MessageObject.TextLayoutBlock pressedCopyCode;
     private LinkSpanDrawable.LinkCollector links = new LinkSpanDrawable.LinkCollector(this);
     private int pressedLinkType;
     private boolean linkPreviewPressed;
@@ -1109,6 +1117,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
     private int backgroundDrawableBottom;
     private int viaWidth;
     private int viaNameWidth;
+    private boolean viaOnly;
     private TypefaceSpan viaSpan1;
     private TypefaceSpan viaSpan2;
     private int availableTimeWidth;
@@ -1261,7 +1270,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
     private TLRPC.FileLocation currentPhoto;
     private String currentNameString;
     private Object currentNameStatus;
-    private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable currentNameStatusDrawable;
+    public AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable currentNameStatusDrawable;
 
     private TLRPC.User currentForwardUser;
     private TLRPC.User currentViaBotUser;
@@ -1595,11 +1604,111 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
         return new int[]{start, end};
     }
 
+    private boolean checkNameMotionEvent(MotionEvent event) {
+        if (!drawNameLayout || nameLayout == null || nameLayoutSelector == null || currentUser == null && currentChat == null) {
+            nameLayoutPressed = false;
+            return false;
+        }
+        final boolean pressed = nameLayoutSelector.getBounds().contains((int) event.getX(), (int) event.getY());
+        if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            nameLayoutPressed = pressed;
+            if (nameLayoutPressed) {
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+                    nameLayoutSelector.setHotspot((int) event.getX(), (int) event.getY());
+                }
+                nameLayoutSelector.setState(pressedState);
+            }
+        } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
+            if (event.getAction() == MotionEvent.ACTION_UP && nameLayoutPressed) {
+                if (delegate != null) {
+                    if (viaOnly) {
+                        if (currentViaBotUser != null && currentViaBotUser.bot_inline_placeholder == null) {
+                            delegate.didPressViaBotNotInline(this, currentViaBotUser != null ? currentViaBotUser.id : 0);
+                        } else {
+                            delegate.didPressViaBot(this, currentViaBotUser != null ? currentViaBotUser.username : currentMessageObject.messageOwner.via_bot_name);
+                        }
+                    } else if (currentUser != null) {
+                        delegate.didPressUserAvatar(this, currentUser, event.getX(), event.getY());
+                    } else if (currentChat != null) {
+                        int id;
+                        TLRPC.Chat chat = currentChat;
+                        if (currentMessageObject.messageOwner.fwd_from != null) {
+                            if ((currentMessageObject.messageOwner.fwd_from.flags & 16) != 0) {
+                                id = currentMessageObject.messageOwner.fwd_from.saved_from_msg_id;
+                            } else {
+                                id = currentMessageObject.messageOwner.fwd_from.channel_post;
+                                chat = currentForwardChannel;
+                            }
+                        } else {
+                            id = 0;
+                        }
+                        delegate.didPressChannelAvatar(this, chat != null ? chat : currentChat, id, lastTouchX, lastTouchY);
+                    }
+                }
+            }
+            nameLayoutSelector.setState(StateSet.NOTHING);
+            nameLayoutPressed = false;
+        }
+        return nameLayoutPressed;
+    }
+
+    private boolean checkNameStatusMotionEvent(MotionEvent event) {
+        if (!drawNameLayout || nameLayout == null || nameLayoutSelector == null || currentUser == null && currentChat == null || currentNameStatus == null || currentNameStatusDrawable == null) {
+            nameStatusPressed = false;
+            return false;
+        }
+        final boolean pressed = nameStatusSelector.getBounds().contains((int) event.getX(), (int) event.getY());
+        if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            nameStatusPressed = pressed;
+            if (nameStatusPressed) {
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+                    nameStatusSelector.setHotspot((int) event.getX(), (int) event.getY());
+                }
+                nameStatusSelector.setState(pressedState);
+            }
+        } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
+            if (event.getAction() == MotionEvent.ACTION_UP && nameStatusPressed) {
+                if (delegate != null) {
+                    if (currentUser != null) {
+                        TLRPC.Document document = null;
+                        if (currentNameStatusDrawable.getDrawable() instanceof AnimatedEmojiDrawable) {
+                            document = ((AnimatedEmojiDrawable) currentNameStatusDrawable.getDrawable()).getDocument();
+                        }
+                        delegate.didPressUserStatus(this, currentUser, document);
+                        invalidateOutbounds();
+                    }
+                }
+            }
+            nameStatusSelector.setState(StateSet.NOTHING);
+            nameStatusPressed = false;
+        }
+        return nameStatusPressed;
+    }
+
+    private void resetCodeSelectors() {
+        if (currentMessageObject != null && currentMessageObject.textLayoutBlocks != null) {
+            for (int i = 0; i < currentMessageObject.textLayoutBlocks.size(); ++i) {
+                MessageObject.TextLayoutBlock block = currentMessageObject.textLayoutBlocks.get(i);
+                if (block.copySelector != null) {
+                    block.copySelector.setState(StateSet.NOTHING);
+                }
+            }
+        }
+        if (captionLayout != null) {
+            for (int i = 0; i < captionLayout.textLayoutBlocks.size(); ++i) {
+                MessageObject.TextLayoutBlock block = captionLayout.textLayoutBlocks.get(i);
+                if (block.copySelector != null) {
+                    block.copySelector.setState(StateSet.NOTHING);
+                }
+            }
+        }
+    }
+
     private boolean checkTextBlockMotionEvent(MotionEvent event) {
         if (!(currentMessageObject.type == MessageObject.TYPE_TEXT || currentMessageObject.type == MessageObject.TYPE_EMOJIS || currentMessageObject.type == MessageObject.TYPE_STORY_MENTION) || currentMessageObject.textLayoutBlocks == null || currentMessageObject.textLayoutBlocks.isEmpty() || !(currentMessageObject.messageText instanceof Spannable)) {
             return false;
         }
-        if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP && (pressedLinkType == 1)) {
+        if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP && (pressedLinkType == 1 || pressedCopyCode != null)) {
             int x = (int) event.getX();
             int y = (int) event.getY();
             if (x >= textX && y >= textY && x <= textX + currentMessageObject.textWidth && y <= textY + currentMessageObject.textHeight) {
@@ -1615,6 +1724,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                     MessageObject.TextLayoutBlock block = currentMessageObject.textLayoutBlocks.get(blockNum);
                     x -= textX - (block.isRtl() ? currentMessageObject.textXOffset : 0);
                     y -= block.textYOffset;
+
+                    if (!block.quote && block.code && x > 0 && x <= currentMessageObject.textWidth && y >= block.padTop + block.height + block.padBottom - dp(38) && y <= block.padTop + block.height + block.padBottom) {
+                        if (event.getAction() == MotionEvent.ACTION_UP) {
+                            if (block == pressedCopyCode && delegate != null) {
+                                delegate.didPressCodeCopy(this, block);
+                            }
+                            resetCodeSelectors();
+                            pressedCopyCode = null;
+                        } else {
+                            pressedCopyCode = block;
+                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+                                block.copySelector.setHotspot(x, y);
+                            }
+                            block.copySelector.setState(pressedState);
+                        }
+                        return true;
+                    }
+
                     final int line = block.textLayout.getLineForVertical(y);
                     final int off = block.charactersOffset + block.textLayout.getOffsetForHorizontal(line, x);
 
@@ -1734,6 +1861,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
             } else {
                 resetPressedLink(1);
             }
+        } else if (event.getAction() == MotionEvent.ACTION_UP) {
+            pressedCopyCode = null;
+            resetCodeSelectors();
         }
         return false;
     }
@@ -1742,7 +1872,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
         if (!(currentCaption instanceof Spannable) || captionLayout == null) {
             return false;
         }
-        if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP && (pressedLinkType == 1)) {
+        if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP && (pressedLinkType == 1 || pressedCopyCode != null)) {
             int x = (int) event.getX();
             int y = (int) event.getY();
             if (x >= captionX && y >= captionY && x <= captionX + captionLayout.textWidth && y <= captionY + captionLayout.textHeight) {
@@ -1758,6 +1888,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                     MessageObject.TextLayoutBlock block = captionLayout.textLayoutBlocks.get(blockNum);
                     x -= captionX - (block.isRtl() ? captionLayout.textXOffset : 0);
                     y -= block.textYOffset;
+
+                    if (!block.quote && block.code && x > 0 && x <= captionLayout.textWidth && y >= block.padTop + block.height + block.padBottom - dp(38) && y <= block.padTop + block.height + block.padBottom) {
+                        if (event.getAction() == MotionEvent.ACTION_UP) {
+                            if (block == pressedCopyCode && delegate != null) {
+                                delegate.didPressCodeCopy(this, block);
+                            }
+                            resetCodeSelectors();
+                            pressedCopyCode = null;
+                        } else {
+                            pressedCopyCode = block;
+                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+                                block.copySelector.setHotspot(x, y);
+                            }
+                            block.copySelector.setState(pressedState);
+                        }
+                        return true;
+                    }
+
                     final int line = block.textLayout.getLineForVertical(y);
                     final int off = block.charactersOffset + block.textLayout.getOffsetForHorizontal(line, x);
 
@@ -1877,6 +2025,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
             } else {
                 resetPressedLink(1);
             }
+        } else if (event.getAction() == MotionEvent.ACTION_UP) {
+            pressedCopyCode = null;
+            resetCodeSelectors();
         }
         return false;
     }
@@ -3096,6 +3247,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
         if (!result) {
             result = checkTextBlockMotionEvent(event);
         }
+        if (!result) {
+            result = checkNameMotionEvent(event);
+        }
+        if (!result) {
+            result = checkNameStatusMotionEvent(event);
+        }
         if (!result) {
             result = checkPinchToZoom(event);
         }
@@ -3174,6 +3331,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                     linkPreviewSelector.setState(StateSet.NOTHING);
                 }
             }
+            if (nameStatusSelector != null) {
+                nameStatusSelector.setState(StateSet.NOTHING);
+            }
+            if (nameLayoutSelector != null) {
+                nameLayoutSelector.setState(StateSet.NOTHING);
+            }
+            resetCodeSelectors();
             if (linkPreviewBounce != null) {
                 linkPreviewBounce.setPressed(false);
             }
@@ -4612,6 +4776,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
             replyTextHeight = 0;
             viaWidth = 0;
             viaNameWidth = 0;
+            viaOnly = false;
             addedCaptionHeight = 0;
             currentReplyPhoto = null;
             currentUser = null;
@@ -4620,6 +4785,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
             instantViewLayout = null;
             drawNameLayout = false;
             linkPreviewAbove = false;
+            isSmallImage = false;
             lastLoadingSizeTotal = 0;
             if (scheduledInvalidate) {
                 AndroidUtilities.cancelRunOnUIThread(invalidateRunnable);
@@ -5135,12 +5301,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                 }
 
                 setMessageObjectInternal(messageObject);
+                giveawayMessageCell.setMessageContent(messageObject, getParentWidth(), forwardedNameWidth);
 
                 backgroundWidth = messageObject.textWidth + getExtraTextX() * 2 + (hasGamePreview || hasInvoicePreview ? AndroidUtilities.dp(10) : 0);
                 totalHeight = messageObject.textHeight + AndroidUtilities.dp(19.5f) + namesOffset;
 
                 if (!reactionsLayoutInBubble.isSmall) {
-                    reactionsLayoutInBubble.measure(maxWidth, Gravity.LEFT);
+                    reactionsLayoutInBubble.measure(messageObject.isGiveaway() ? giveawayMessageCell.getMeasuredWidth() : maxWidth, Gravity.LEFT);
                     if (!reactionsLayoutInBubble.isEmpty) {
                         reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(8);
                         if (reactionsLayoutInBubble.width > backgroundWidth) {
@@ -5169,8 +5336,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                 }
                 int maxWebWidth = 0;
 
-                giveawayMessageCell.setMessageContent(messageObject, getParentWidth(), forwardedNameWidth);
-
                 if (hasLinkPreview || hasGamePreview || hasInvoicePreview) {
                     int linkPreviewMaxWidth;
                     if (AndroidUtilities.isTablet()) {
@@ -8424,6 +8589,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
             replySelector.setState(new int[]{});
             invalidate();
         }
+        if (nameStatusSelector != null) {
+            nameStatusSelector.setState(StateSet.NOTHING);
+        }
+        if (nameLayoutSelector != null) {
+            nameLayoutSelector.setState(StateSet.NOTHING);
+        }
+        resetCodeSelectors();
         if (replyBounce != null) {
             replyBounce.setPressed(false);
         }
@@ -8977,6 +9149,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
         if (
             currentMessageObject.hasCodeAtBottom && (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) ||
             currentMessageObject.hasQuoteAtBottom && (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall)
+            || currentMessageObject.isGiveaway()
         ) {
             newLineForTime = true;
             newLineForTimeDp = 18;
@@ -9265,7 +9438,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
 
     @Override
     protected boolean verifyDrawable(Drawable who) {
-        return super.verifyDrawable(who) || who == selectorDrawable[0] || who == selectorDrawable[1] || who == linkPreviewSelector;
+        return super.verifyDrawable(who) || who == selectorDrawable[0] || who == selectorDrawable[1] || who == linkPreviewSelector || who == nameLayoutSelector || who == replySelector;
     }
 
     @Override
@@ -11797,6 +11970,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
         if (textLayoutBlocks == null || textLayoutBlocks.isEmpty() || alpha == 0) {
             return;
         }
+
         int firstVisibleBlockNum;
         int lastVisibleBlockNum;
         if (origin && !drawAllBlocks) {
@@ -11867,39 +12041,35 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
         }
 
         if (firstVisibleBlockNum >= 0) {
-            final float maxWidth;
-            if (caption) {
-                if (currentMessagesGroup != null) {
-                    float endX = textX - getExtraTextX();
-                    if (currentMessagesGroup != null && !currentMessageObject.isMusic() && !currentMessageObject.isDocument()) {
-                        int dWidth = getGroupPhotosWidth();
-                        if ((currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0) {
-                            endX += Math.ceil(currentPosition.pw / 1000.0f * dWidth);
-                        } else {
-                            int firstLineWidth = 0;
-                            for (int i = 0; i < currentMessagesGroup.posArray.size(); i++) {
-                                MessageObject.GroupedMessagePosition position = currentMessagesGroup.posArray.get(i);
-                                if (position.minY == 0) {
-                                    firstLineWidth += Math.ceil((position.pw + position.leftSpanOffset) / 1000.0f * dWidth);
-                                } else {
-                                    break;
-                                }
-                            }
-                            endX += firstLineWidth - AndroidUtilities.dp(9);
-                        }
-                    } else {
-                        endX += backgroundWidth - (mediaBackground ? 0 : AndroidUtilities.dp(9));
-                    }
-                    if (currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0 && !currentMessagesGroup.hasSibling) {
-                        endX += AndroidUtilities.dp(14);
-                    }
-                    maxWidth = endX - textX - AndroidUtilities.dp(6 + 4 + (currentMessageObject.isOutOwner() && !drawPinnedBottom ? 6 : 0));
-                } else {
-                    maxWidth = captionFullWidth - AndroidUtilities.dp(3 + (currentMessageObject.isOutOwner() && !drawPinnedBottom ? 6 : 0)) - 2 * getExtraTextX();
-                }
+            float right;
+            if (currentMessagesGroup == null || currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_RIGHT) != 0) {
+                right = getBackgroundDrawableRight() + transitionParams.deltaRight;
             } else {
-                maxWidth = getCurrentBackgroundRight() - AndroidUtilities.dp(11 + (currentMessageObject.isOutOwner() && !drawPinnedBottom ? 6 : 0)) - getExtraTextX() - textX;
+                int end, dWidth;
+                if (AndroidUtilities.isTablet()) {
+                    dWidth = AndroidUtilities.getMinTabletSide();
+                } else {
+                    dWidth = getParentWidth();
+                }
+                int firstLineWidth = 0;
+                for (int a = 0; a < currentMessagesGroup.posArray.size(); a++) {
+                    MessageObject.GroupedMessagePosition position = currentMessagesGroup.posArray.get(a);
+                    if (position.minY == 0) {
+                        firstLineWidth += Math.ceil((position.pw + position.leftSpanOffset) / 1000.0f * dWidth);
+                    } else {
+                        break;
+                    }
+                }
+                if (!mediaBackground && currentMessageObject.isOutOwner()) {
+                    end = backgroundDrawableLeft + firstLineWidth - AndroidUtilities.dp(6);
+                } else {
+                    end = backgroundDrawableLeft + firstLineWidth;
+                }
+                end -= getExtraTextX() + AndroidUtilities.dp(8 + (isAvatarVisible ? 48 : 0));
+                right = end;
             }
+            right -= AndroidUtilities.dp(10 + (currentMessageObject.isOutOwner() && !mediaBackground && !drawPinnedBottom ? 6 : 0)) + getExtraTextX();
+            final float maxWidth = right - textX;
             int restore = Integer.MIN_VALUE;
             int oldAlpha = 0;
             int oldLinkAlpha = 0;
@@ -11964,7 +12134,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                     quoteLine.check(currentMessageObject, currentUser, currentChat, resourcesProvider, false);
 
                     final int width = (int) (block.maxRight + AndroidUtilities.dp(24) > maxWidth * .7f ? maxWidth : block.maxRight + AndroidUtilities.dp(24));
-                    AndroidUtilities.rectTmp.set((block.isRtl() ? rtlOffset - AndroidUtilities.dp(10) : 0), -block.padTop + AndroidUtilities.dp(block.first ? 3 + 1.66f : 3), (block.isRtl() ? rtlOffset - AndroidUtilities.dp(10) : 0) + width, block.height + AndroidUtilities.dp(4));
+                    AndroidUtilities.rectTmp.set(0, -block.padTop + AndroidUtilities.dp(block.first ? 3 + 1.66f : 3), width, block.height + AndroidUtilities.dp(4));
+                    AndroidUtilities.rectTmp.offset((block.isRtl() ? rtlOffset - AndroidUtilities.dp(10) : 0), 0);
                     quoteLine.drawBackground(canvas, AndroidUtilities.rectTmp, 5, 5, 5, alpha);
                     quoteLine.drawLine(canvas, AndroidUtilities.rectTmp, alpha);
 
@@ -11975,10 +12146,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                         replyQuoteDrawable.setColorFilter(new PorterDuffColorFilter(replyQuoteDrawableColor = quoteLine.getColor(), PorterDuff.Mode.SRC_IN));
                     }
                     replyQuoteDrawable.setBounds(
-                            (int) (AndroidUtilities.rectTmp.right - AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0)) - replyQuoteDrawable.getIntrinsicWidth()),
-                            (int) (AndroidUtilities.rectTmp.top + AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0))),
-                            (int) (AndroidUtilities.rectTmp.right - AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0))),
-                            (int) (AndroidUtilities.rectTmp.top + AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0)) + replyQuoteDrawable.getIntrinsicHeight())
+                            (int) (AndroidUtilities.rectTmp.right - dp(2 + (!drawPinnedTop ? 1 : 0)) - replyQuoteDrawable.getIntrinsicWidth()),
+                            (int) (AndroidUtilities.rectTmp.top + dp(2 + (!drawPinnedTop ? 1 : 0))),
+                            (int) (AndroidUtilities.rectTmp.right - dp(2 + (!drawPinnedTop ? 1 : 0))),
+                            (int) (AndroidUtilities.rectTmp.top + dp(2 + (!drawPinnedTop ? 1 : 0)) + replyQuoteDrawable.getIntrinsicHeight())
                     );
                     replyQuoteDrawable.setAlpha((int) (0xFF * alpha));
                     replyQuoteDrawable.draw(canvas);
@@ -11996,29 +12167,36 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                     Theme.chat_msgTextPaint.linkColor = getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_messageLinkOut : Theme.key_chat_messageLinkIn);
 
                     if (block.code) {
-                        Theme.chat_msgCodeBgPaint.setColor(Theme.getColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outCodeBackground : Theme.key_chat_inCodeBackground, resourcesProvider));
-                        Theme.chat_msgCodeBgPaint.setAlpha((int) (Theme.chat_msgCodeBgPaint.getAlpha() * alpha));
+                        if (quoteLine == null) {
+                            quoteLine = new ReplyMessageLine(this);
+                        }
+                        quoteLine.check(currentMessageObject, currentUser, currentChat, resourcesProvider, false);
+                        if (currentMessageObject.isOutOwner() && (Theme.isCurrentThemeDark() || Theme.isCustomTheme())) {
+                            quoteLine.setBackgroundColor(getThemedColor(Theme.key_chat_outCodeBackground));
+                        }
+                        AndroidUtilities.rectTmp.set(0, -dp(2 + 4) - block.languageHeight, maxWidth + dp(4), block.height + dp(2 + 4));
+                        AndroidUtilities.rectTmp.offset((block.isRtl() ? rtlOffset : 0), 0);
+                        if (block.hasCodeCopyButton) {
+                            AndroidUtilities.rectTmp.bottom += dp(38);
+                        }
+                        final float rightRad = block.first && namesOffset <= 0 && !caption ? ((!currentMessageObject.isOutOwner() || !pinnedTop) ? SharedConfig.bubbleRadius / 3f * 2f : Math.min(6, SharedConfig.bubbleRadius)) : Math.min(5, SharedConfig.bubbleRadius);;
+                        quoteLine.drawBackground(canvas, AndroidUtilities.rectTmp, 5, rightRad, Math.min(5, SharedConfig.bubbleRadius), alpha);
+                        if (block.languageHeight > 0) {
+                            float wasBottom = AndroidUtilities.rectTmp.bottom;
+                            AndroidUtilities.rectTmp.bottom = AndroidUtilities.rectTmp.top + block.languageHeight;
+                            quoteLine.drawBackground(canvas, AndroidUtilities.rectTmp, 5, rightRad, 0, (Theme.isCurrentThemeDark() ? .60f : .80f) * alpha);
+                            AndroidUtilities.rectTmp.bottom = wasBottom;
+                        }
+                        quoteLine.drawLine(canvas, AndroidUtilities.rectTmp, alpha);
 
-                        AndroidUtilities.rectTmp.set(-AndroidUtilities.dp(4), -AndroidUtilities.dp(2), maxWidth + AndroidUtilities.dp(4), block.height + AndroidUtilities.dp(2));
-                        if (replyRoundRectPath == null) {
-                            replyRoundRectPath = new Path();
-                        } else {
-                            replyRoundRectPath.rewind();
+                        if (block.hasCodeCopyButton) {
+                            block.drawCopyCodeButton(canvas, AndroidUtilities.rectTmp, quoteLine.getColor(), quoteLine.getBackgroundColor(), alpha);
                         }
-                        if (replyBackgroundRadii == null) {
-                            replyBackgroundRadii = new float[8];
+
+                        canvas.translate(dp(10), 0);
+                        if (block.languageLayout != null) {
+                            block.languageLayout.ellipsize((int) (maxWidth - dp(8 + 4))).draw(canvas, 0, -dp(6) - block.languageHeight / 2f, quoteLine.getColor(), alpha);
                         }
-                        final int rad = dp(SharedConfig.bubbleRadius);
-                        final int nearRad = dp(Math.min(6, SharedConfig.bubbleRadius));
-                        final int defrad = dp(Math.min(5, SharedConfig.bubbleRadius));
-                        replyBackgroundRadii[0] = replyBackgroundRadii[1] = block.first && namesOffset <= 0 && !caption ? ((currentMessageObject.isOutOwner() || !pinnedTop) ? rad / 3f * 2f : nearRad) : defrad;
-                        replyBackgroundRadii[2] = replyBackgroundRadii[3] = block.first && namesOffset <= 0 && !caption ? ((!currentMessageObject.isOutOwner() || !pinnedTop) ? rad / 3f * 2f : nearRad) : defrad;
-                        replyBackgroundRadii[4] = replyBackgroundRadii[5] = replyBackgroundRadii[6] = replyBackgroundRadii[7] = defrad;
-                        replyRoundRectPath.addRoundRect(AndroidUtilities.rectTmp, replyBackgroundRadii, Path.Direction.CW);
-                        canvas.save();
-                        canvas.translate((block.isRtl() ? rtlOffset - (block.quote ? AndroidUtilities.dp(10) : 0) : 0), 0);
-                        canvas.drawPath(replyRoundRectPath, Theme.chat_msgCodeBgPaint);
-                        canvas.restore();
                     }
                 }
                 if (a == linkSelectionBlockNum && quoteHighlight == null && !urlPathSelection.isEmpty() && !drawOnlyText) {
@@ -13485,7 +13663,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                 } else {
                     TLRPC.EncryptedChat echat = messagesController.getEncryptedChat(DialogObject.getEncryptedChatId(currentMessageObject.getDialogId()));
                     if (echat != null) {
-                        currentUser = messagesController.getUser(echat.participant_id);
+                        currentUser = messagesController.getUser(echat.user_id);
                     }
                 }
             } else if (DialogObject.isUserDialog(fromId) && !currentMessageObject.messageOwner.post) {
@@ -13590,9 +13768,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                 if (currentNameString.length() > 0) {
                     SpannableStringBuilder stringBuilder = new SpannableStringBuilder(String.format("%s %s %s", nameStringFinal, viaBotString, viaUsername));
                     stringBuilder.setSpan(viaSpan1 = new TypefaceSpan(Typeface.DEFAULT, 0, color), nameStringFinal.length() + 1, nameStringFinal.length() + 1 + viaBotString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    if (currentNameStatus != null) {
+                        viaNameWidth += dp(4 + 20 + 4);
+                        stringBuilder.setSpan(new DialogCell.FixedWidthSpan(dp(4 + 20 + 4)), nameStringFinal.length(), nameStringFinal.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    }
                     stringBuilder.setSpan(viaSpan2 = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, color), nameStringFinal.length() + 2 + viaBotString.length(), stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                     nameStringFinal = stringBuilder;
                 } else {
+                    viaOnly = true;
                     SpannableStringBuilder stringBuilder = new SpannableStringBuilder(String.format("%s %s", viaBotString, viaUsername));
                     stringBuilder.setSpan(viaSpan1 = new TypefaceSpan(Typeface.DEFAULT, 0, color), 0, viaBotString.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                     stringBuilder.setSpan(viaSpan2 = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, color), 1 + viaBotString.length(), stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -13811,7 +13994,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                 int maxWidth = getMaxNameWidth();
                 if (!messageObject.shouldDrawWithoutBackground()) {
                     maxWidth -= AndroidUtilities.dp(messageObject.isOutOwner() ? 20 : 10);
-                    if (messageObject.type != MessageObject.TYPE_TEXT) {
+                    if (messageObject.type != MessageObject.TYPE_TEXT || messageObject.needDrawShareButton()) {
                         maxWidth -= AndroidUtilities.dp(10);
                     }
                 } else if (messageObject.type == MessageObject.TYPE_ROUND_VIDEO) {
@@ -13910,8 +14093,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                     if (DialogObject.isEncryptedDialog(messageObject.getDialogId())) {
                         if (messageObject.replyMessageObject != null && messageObject.replyMessageObject.isOutOwner()) {
                             name = UserObject.getUserName(UserConfig.getInstance(currentAccount).getCurrentUser());
-                        } else if (currentUser != null) {
-                            name = UserObject.getUserName(currentUser);
+                        } else {
+                            TLRPC.EncryptedChat echat = MessagesController.getInstance(currentAccount).getEncryptedChat(DialogObject.getEncryptedChatId(currentMessageObject.getDialogId()));
+                            if (echat != null) {
+                                name = UserObject.getUserName(MessagesController.getInstance(currentAccount).getUser(echat.user_id));
+                            }
                         }
                     } else if (hasReplyQuote && !DialogObject.isEncryptedDialog(messageObject.getDialogId())) {
                         name = messageObject.getReplyQuoteNameWithIcon();
@@ -15205,9 +15391,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                 nx = nameX;
             }
             currentNameStatusDrawable.setBounds(
-                (int) (Math.abs(nx) + nameLayoutWidth + AndroidUtilities.dp(2)),
+                (int) (Math.abs(nx) + (viaNameWidth > 0 ? viaNameWidth - dp(4 + 28) : nameLayoutWidth) + AndroidUtilities.dp(2)),
                 (int) (nameY + nameLayout.getHeight() / 2 - AndroidUtilities.dp(10)),
-                (int) (Math.abs(nx) + nameLayoutWidth + AndroidUtilities.dp(22)),
+                (int) (Math.abs(nx) + (viaNameWidth > 0 ? viaNameWidth - dp(4 + 28) : nameLayoutWidth) + AndroidUtilities.dp(22)),
                 (int) (nameY + nameLayout.getHeight() / 2 + AndroidUtilities.dp(10))
             );
             currentNameStatusDrawable.setColor(ColorUtils.setAlphaComponent(color, 115));
@@ -15743,6 +15929,40 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
             } else {
                 nx = nameX;
             }
+
+            if (!currentMessageObject.isSponsored()) {
+                int selectorColor = Theme.multAlpha(Theme.chat_namePaint.getColor(), .12f);
+                if (nameLayoutSelector == null) {
+                    nameLayoutSelector = Theme.createRadSelectorDrawable(nameLayoutSelectorColor = selectorColor, 6, 6);
+                    nameLayoutSelector.setCallback(this);
+                } else if (nameLayoutSelectorColor != selectorColor) {
+                    Theme.setSelectorDrawableColor(nameLayoutSelector, nameLayoutSelectorColor = selectorColor, true);
+                }
+                nameLayoutSelector.setBounds(
+                    (int) (nx - dp(4)),
+                    (int) (nameY - dp(1.33f)),
+                    (int) (nx + (viaNameWidth > 0 ? viaNameWidth - dp(4 + 28) : nameLayoutWidth) + dp(4)),
+                    (int) (nameY + nameLayout.getHeight() + dp(1.33f))
+                );
+                nameLayoutSelector.draw(canvas);
+
+                if (currentNameStatus != null) {
+                    if (nameStatusSelector == null) {
+                        nameStatusSelector = Theme.createRadSelectorDrawable(nameStatusSelectorColor = selectorColor, 6, 6);
+                        nameStatusSelector.setCallback(this);
+                    } else if (nameStatusSelectorColor != selectorColor) {
+                        Theme.setSelectorDrawableColor(nameStatusSelector, nameStatusSelectorColor = selectorColor, true);
+                    }
+                    nameStatusSelector.setBounds(
+                        (int) (nx + (viaNameWidth > 0 ? viaNameWidth - dp(4 + 28) : nameLayoutWidth)),
+                        (int) (nameY - dp(1.33f + 2)),
+                        (int) (nx + (viaNameWidth > 0 ? viaNameWidth - dp(4 + 28) : nameLayoutWidth) + dp(4 + 12 + 4 + 4)),
+                        (int) (nameY + nameLayout.getHeight() + dp(1.33f + 2))
+                    );
+                    nameStatusSelector.draw(canvas);
+                }
+            }
+
             canvas.translate(nx, nameY);
             nameLayout.draw(canvas);
             canvas.restore();
@@ -16268,7 +16488,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                 if (needReplyImage) {
                     replyImageReceiver.setAlpha(replyForwardAlpha);
                     replyImageSz = Math.min(replySelectorRect.height() - AndroidUtilities.dp(10), AndroidUtilities.dp(isReplyQuote ? 3 : 7) + Theme.chat_replyNamePaint.getTextSize() + Theme.chat_replyTextPaint.getTextSize());
-                    replyImageReceiver.setImageCoords(replySelectorRect.left + AndroidUtilities.dp(8), replySelectorRect.top + AndroidUtilities.dp(5), replyImageSz, replyImageSz);
+                    replyImageReceiver.setImageCoords(replySelectorRect.left + AndroidUtilities.dp(8), replySelectorRect.top + AndroidUtilities.dp((isReplyQuote && replyTextLayout != null && replyTextLayout.getLineCount() <= 1 ? 2 : 0) + 5), replyImageSz, replyImageSz);
                     replyImageReceiver.draw(canvas);
 
                     if (currentMessageObject != null && currentMessageObject.hasValidReplyMessageObject() && currentMessageObject.replyMessageObject.hasMediaSpoilers()) {
@@ -16336,7 +16556,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                     if (needReplyImage && (!isReplyQuote || replyTextRTL)) {
                         left += replyImageSz + AndroidUtilities.dp(3);
                     }
-                    if (replyTextRTL) {
+                    if (replyTextRTL && transitionParams.animateReplyTextOffset > 0) {
                         left = replySelectorRect.right - AndroidUtilities.dp(8) - transitionParams.animateReplyTextLayout.getWidth();
                     }
                     canvas.translate(left, replyStartY + offsetY - AndroidUtilities.dp(1) + Theme.chat_replyNamePaint.getTextSize() + AndroidUtilities.dp(5));
@@ -16357,7 +16577,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
                     if (needReplyImage && (!isReplyQuote || replyTextRTL)) {
                         left += replyImageSz + AndroidUtilities.dp(3);
                     }
-                    if (replyTextRTL) {
+                    if (replyTextRTL && replyTextOffset > 0) {
                         left = replySelectorRect.right - AndroidUtilities.dp(8) - replyTextLayout.getWidth();
                     }
                     canvas.translate(left, replyStartY + offsetY - AndroidUtilities.dp(1) + Theme.chat_replyNamePaint.getTextSize() + AndroidUtilities.dp(5));
@@ -20990,4 +21210,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
         }
         return fancyBlurFilter;
     }
+
+    public int getNameStatusX() {
+        return (int) (nameX + (viaNameWidth > 0 ? viaNameWidth - dp(4 + 28) : nameLayoutWidth) + dp(2) + dp(4 + 12 + 4) / 2);
+    }
+
+    public int getNameStatusY() {
+        return (int) (nameY + (nameLayout == null ? 0 : nameLayout.getHeight()) / 2);
+    }
 }
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 96569d907..279dfd631 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java
@@ -2171,6 +2171,15 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
 
         try {
             CharSequence messageStringFinal;
+            // Removing links and bold spans to get rid of underlining and boldness
+            if (messageString instanceof Spannable) {
+                Spannable messageStringSpannable = (Spannable) messageString;
+                for (Object span : messageStringSpannable.getSpans(0, messageStringSpannable.length(), Object.class)) {
+                    if (span instanceof ClickableSpan || span instanceof CodeHighlighting.Span || span instanceof CodeHighlighting.ColorSpan || span instanceof QuoteSpan || span instanceof QuoteSpan.QuoteStyleSpan || (span instanceof StyleSpan && ((StyleSpan) span).getStyle() == android.graphics.Typeface.BOLD)) {
+                        messageStringSpannable.removeSpan(span);
+                    }
+                }
+            }
             if ((useForceThreeLines || SharedConfig.useThreeLinesLayout) && currentDialogFolderId != 0 && currentDialogFolderDialogsCount > 1) {
                 messageStringFinal = messageNameString;
                 messageNameString = null;
@@ -2184,15 +2193,6 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
             } else {
                 messageStringFinal = messageString;
             }
-            // Removing links and bold spans to get rid of underlining and boldness
-            if (messageStringFinal instanceof Spannable) {
-                Spannable messageStringSpannable = (Spannable) messageStringFinal;
-                for (Object span : messageStringSpannable.getSpans(0, messageStringSpannable.length(), Object.class)) {
-                    if (span instanceof ClickableSpan || span instanceof CodeHighlighting.Span || span instanceof CodeHighlighting.ColorSpan || span instanceof QuoteSpan || span instanceof QuoteSpan.QuoteStyleSpan || (span instanceof StyleSpan && ((StyleSpan) span).getStyle() == android.graphics.Typeface.BOLD)) {
-                        messageStringSpannable.removeSpan(span);
-                    }
-                }
-            }
 
             Layout.Alignment align = isForum && LocaleController.isRTL ? Layout.Alignment.ALIGN_OPPOSITE : Layout.Alignment.ALIGN_NORMAL;
             if (useForceThreeLines || SharedConfig.useThreeLinesLayout) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RecurrentPaymentsAcceptCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RecurrentPaymentsAcceptCell.java
index 27d397506..b34c7f741 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RecurrentPaymentsAcceptCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RecurrentPaymentsAcceptCell.java
@@ -46,6 +46,10 @@ public class RecurrentPaymentsAcceptCell extends FrameLayout {
         return textView;
     }
 
+    public CheckBoxSquare getCheckBox() {
+        return checkBox;
+    }
+
     public void setText(CharSequence text) {
         textView.setText(text);
     }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java
index a90050768..46dca248e 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java
@@ -1,6 +1,7 @@
 package org.telegram.ui.Cells;
 
 import static com.google.zxing.common.detector.MathUtils.distance;
+import static org.telegram.messenger.AndroidUtilities.dp;
 import static org.telegram.ui.ActionBar.FloatingToolbar.STYLE_THEME;
 import static org.telegram.ui.ActionBar.Theme.key_chat_inTextSelectionHighlight;
 
@@ -156,7 +157,7 @@ public abstract class TextSelectionHelper> 1;
                 } else {
@@ -218,7 +219,7 @@ public abstract class TextSelectionHelper layoutBlock.layout.getLineLeft(endLine)) {
+                if (x < layoutBlock.layout.getLineRight(endLine) + dp(4) && x > layoutBlock.layout.getLineLeft(endLine)) {
                     offset = text.length() - 1;
                 }
             }
@@ -306,7 +307,7 @@ public abstract class TextSelectionHelper textArea.right) x = textArea.right - 1;
@@ -366,7 +367,7 @@ public abstract class TextSelectionHelper layoutBlock.layout.getLineLeft(endLine)) {
+                        if (x < layoutBlock.layout.getLineRight(endLine) + dp(4) && x > layoutBlock.layout.getLineLeft(endLine)) {
                             offset = text.length() - 1;
                         }
                     }
@@ -419,11 +420,11 @@ public abstract class TextSelectionHelper {
@@ -559,7 +560,7 @@ public abstract class TextSelectionHelper 0 && y + yOffset - getLineHeight() < parentView.getMeasuredHeight()) {
@@ -1543,7 +1544,7 @@ public abstract class TextSelectionHelper= block.textYOffset && y <= block.textYOffset + block.padTop + block.height) {
                         layoutBlock.layout = block.textLayout;
                         layoutBlock.yOffset = block.textYOffset + block.padTop;
-                        layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(captionLayout.textXOffset) - (block.quote ? AndroidUtilities.dp(10) : 0) : 0);
+                        int offsetX = 0;
+                        if (block.quote) {
+                            offsetX = dp(10);
+                        }
+                        layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(captionLayout.textXOffset) - offsetX : 0);
+                        if (block.code && !block.quote) {
+                            layoutBlock.xOffset += dp(8);
+                        }
                         layoutBlock.charOffset = block.charactersOffset;
                         return;
                     }
@@ -2189,7 +2209,16 @@ public abstract class TextSelectionHelper= block.textYOffset && y <= block.textYOffset + block.padTop + block.height) {
                     layoutBlock.layout = block.textLayout;
                     layoutBlock.yOffset = block.textYOffset + block.padTop;
-                    layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(messageObject.textXOffset) - (block.quote ? AndroidUtilities.dp(10) : 0) : 0);
+                    int offsetX = 0;
+                    if (block.quote) {
+                        offsetX = dp(10);
+                    } else if (block.code) {
+                        offsetX = dp(0);
+                    }
+                    layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(messageObject.textXOffset) - offsetX : 0);
+                    if (block.code && !block.quote) {
+                        layoutBlock.xOffset += dp(8);
+                    }
                     layoutBlock.charOffset = block.charactersOffset;
                     return;
                 }
@@ -2215,9 +2244,18 @@ public abstract class TextSelectionHelper= 0 && blockOffset <= block.textLayout.getText().length()) {
                         layoutBlock.layout = block.textLayout;
                         layoutBlock.yOffset = block.textYOffset + block.padTop;
-                        layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(captionLayout.textXOffset) - (block.quote ? AndroidUtilities.dp(10) : 0) : 0);
+                        int offsetX = 0;
+                        if (block.quote) {
+                            offsetX = dp(10);
+                        }
+                        layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(captionLayout.textXOffset) - offsetX : 0);
+                        if (block.code && !block.quote) {
+                            layoutBlock.xOffset += dp(8);
+                        }
                         layoutBlock.charOffset = block.charactersOffset;
                         return;
                     }
@@ -2243,9 +2288,18 @@ public abstract class TextSelectionHelper= 0 && blockOffset <= block.textLayout.getText().length()) {
                     layoutBlock.layout = block.textLayout;
                     layoutBlock.yOffset = block.textYOffset + block.padTop;
-                    layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(messageObject.textXOffset) - (block.quote ? AndroidUtilities.dp(10) : 0) : 0);
+                    int offsetX = 0;
+                    if (block.quote) {
+                        offsetX = dp(10);
+                    }
+                    layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(messageObject.textXOffset) - offsetX : 0);
+                    if (block.code && !block.quote) {
+                        layoutBlock.xOffset += dp(8);
+                    }
                     layoutBlock.charOffset = block.charactersOffset;
                     return;
                 }
@@ -2582,7 +2643,7 @@ public abstract class TextSelectionHelper 0) {
-                    if (minDistance < AndroidUtilities.dp(24)) {
+                    if (minDistance < dp(24)) {
                         int minDistanceX = Integer.MAX_VALUE;
                         int minIndexX = minIndex;
 
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelBoostLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelBoostLayout.java
index 3ef7b9c67..9d2cb2956 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelBoostLayout.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelBoostLayout.java
@@ -289,8 +289,8 @@ public class ChannelBoostLayout extends FrameLayout {
                 ItemInternal item = items.get(position);
                 TL_stories.TL_prepaidGiveaway prepaidGiveaway = item.prepaidGiveaway;
                 GiveawayCell giveawayCell = (GiveawayCell) holder.itemView;
-                String name = LocaleController.formatString("TelegramPremiumCount", R.string.TelegramPremiumCount, prepaidGiveaway.quantity);
-                String info = LocaleController.formatString("SubscriptionsCount", R.string.SubscriptionsCount, LocaleController.formatPluralString("GiftMonths", prepaidGiveaway.months));
+                String name = LocaleController.formatPluralString("BoostingTelegramPremiumCountPlural", prepaidGiveaway.quantity);
+                String info = LocaleController.formatPluralString("BoostingSubscriptionsCountPlural", prepaidGiveaway.quantity, LocaleController.formatPluralString("PrepaidGiveawayMonths", prepaidGiveaway.months));
                 giveawayCell.setData(prepaidGiveaway, name, info, 0, !item.isLast);
                 giveawayCell.setImage(prepaidGiveaway);
                 giveawayCell.setAvatarPadding(5);
@@ -352,6 +352,7 @@ public class ChannelBoostLayout extends FrameLayout {
                     giftCode.months = (boost.expires - boost.date) / 30 / 86400;
                     if (boost.unclaimed) {
                         giftCode.to_id = NO_USER_ID;
+                        giftCode.flags = -1;
                     } else {
                         giftCode.boost = boost;
                     }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java
index d7a4763b0..786b24fa0 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java
@@ -130,12 +130,14 @@ import org.telegram.messenger.ChatThemeController;
 import org.telegram.messenger.CodeHighlighting;
 import org.telegram.messenger.ContactsController;
 import org.telegram.messenger.DialogObject;
+import org.telegram.messenger.DocumentObject;
 import org.telegram.messenger.DownloadController;
 import org.telegram.messenger.Emoji;
 import org.telegram.messenger.EmojiData;
 import org.telegram.messenger.FileLoader;
 import org.telegram.messenger.FileLog;
 import org.telegram.messenger.FlagSecureReason;
+import org.telegram.messenger.ImageLoader;
 import org.telegram.messenger.ImageLocation;
 import org.telegram.messenger.ImageReceiver;
 import org.telegram.messenger.LanguageDetector;
@@ -153,6 +155,7 @@ import org.telegram.messenger.R;
 import org.telegram.messenger.SecretChatHelper;
 import org.telegram.messenger.SendMessagesHelper;
 import org.telegram.messenger.SharedConfig;
+import org.telegram.messenger.SvgHelper;
 import org.telegram.messenger.TranslateController;
 import org.telegram.messenger.UserConfig;
 import org.telegram.messenger.UserObject;
@@ -9117,7 +9120,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
         float pendingViewH = 0;
         View pendingRequestsView = pendingRequestsDelegate != null ? pendingRequestsDelegate.getView() : null;
         if (pendingRequestsView != null && pendingRequestsView.getVisibility() == View.VISIBLE) {
-            pendingViewH = Math.max(0, pendingRequestsView.getHeight() + pendingRequestsDelegate.getViewEnterOffset());
+            pendingViewH = Math.max(0, pendingRequestsView.getHeight() + pendingRequestsDelegate.getViewEnterOffset() - AndroidUtilities.dp(4));
         }
         float oldPadding = chatListViewPaddingTop;
         chatListViewPaddingTop = AndroidUtilities.dp(4) + contentPaddingTop + topPanelViewH + pinnedViewH + pendingViewH;
@@ -11008,7 +11011,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
 
     @Override
     public boolean dismissDialogOnPause(Dialog dialog) {
-        return dialog != chatAttachAlert && dialog != chatThemeBottomSheet && super.dismissDialogOnPause(dialog);
+        return dialog != chatAttachAlert && dialog != chatThemeBottomSheet && !(dialog instanceof BotWebViewSheet) && super.dismissDialogOnPause(dialog);
     }
 
     int waitingForWebpageId;
@@ -28624,6 +28627,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
                 if (!messageObject.isMusic() && messageObject.replyMessageObject != null) {
                     messageObject = messagesDict[messageObject.replyMessageObject.getDialogId() == dialog_id ? 0 : 1].get(messageObject.replyMessageObject.getId());
                 }
+                if (messageObject == null) {
+                    return;
+                }
                 float progress = seekTime / (float) messageObject.getDuration();
                 MediaController mediaController = getMediaController();
                 if (mediaController.isPlayingMessage(messageObject)) {
@@ -30391,6 +30397,69 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
             showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true));
         }
 
+        @Override
+        public void didPressUserStatus(ChatMessageCell cell, TLRPC.User user, TLRPC.Document document) {
+            if (cell == null) {
+                return;
+            }
+            PremiumPreviewBottomSheet premiumPreviewBottomSheet = new PremiumPreviewBottomSheet(ChatActivity.this, currentAccount, user, themeDelegate);
+            int[] coords = new int[2];
+            cell.getLocationOnScreen(coords);
+            premiumPreviewBottomSheet.startEnterFromX = cell.getNameStatusX();
+            premiumPreviewBottomSheet.startEnterFromY = cell.getNameStatusY();
+            premiumPreviewBottomSheet.startEnterFromScale = cell.getScaleX();
+            premiumPreviewBottomSheet.startEnterFromX1 = cell.getLeft();
+            premiumPreviewBottomSheet.startEnterFromY1 = cell.getTop();
+            premiumPreviewBottomSheet.startEnterFromView = cell;
+            int colorId = user != null ? (int) (user.id % 7) : 0;
+            if (user != null && (user.flags2 & 128) != 0) {
+                colorId = user.color;
+            }
+            if (colorId < 7) {
+                premiumPreviewBottomSheet.accentColor = getThemedColor(Theme.keys_avatar_nameInMessage[colorId]);
+            } else {
+                final MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors;
+                final MessagesController.PeerColor peerColor = peerColors != null ? peerColors.getColor(colorId) : null;
+                premiumPreviewBottomSheet.accentColor = peerColor != null ? peerColor.getColor1() : null;
+            }
+            if (cell.currentNameStatusDrawable != null && cell.currentNameStatusDrawable.getDrawable() instanceof AnimatedEmojiDrawable) {
+                premiumPreviewBottomSheet.startEnterFromScale *= 0.95f;
+                if (document != null) {
+                    BackupImageView icon = new BackupImageView(getContext());
+                    String filter = "160_160";
+                    ImageLocation mediaLocation;
+                    String mediaFilter;
+                    SvgHelper.SvgDrawable thumbDrawable = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f);
+                    TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90);
+                    if ("video/webm".equals(document.mime_type)) {
+                        mediaLocation = ImageLocation.getForDocument(document);
+                        mediaFilter = filter + "_" + ImageLoader.AUTOPLAY_FILTER;
+                        if (thumbDrawable != null) {
+                            thumbDrawable.overrideWidthAndHeight(512, 512);
+                        }
+                    } else {
+                        if (thumbDrawable != null && MessageObject.isAnimatedStickerDocument(document, false)) {
+                            thumbDrawable.overrideWidthAndHeight(512, 512);
+                        }
+                        mediaLocation = ImageLocation.getForDocument(document);
+                        mediaFilter = filter;
+                    }
+                    icon.setLayerNum(7);
+                    icon.setRoundRadius(AndroidUtilities.dp(4));
+                    icon.setImage(mediaLocation, mediaFilter, ImageLocation.getForDocument(thumb, document), "140_140", thumbDrawable, document);
+                    if (MessageObject.isTextColorEmoji(document)) {
+                        icon.setColorFilter(new PorterDuffColorFilter(premiumPreviewBottomSheet.accentColor != null ? premiumPreviewBottomSheet.accentColor : getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon), PorterDuff.Mode.SRC_IN));
+                        premiumPreviewBottomSheet.statusStickerSet = MessageObject.getInputStickerSet(document);
+                    } else {
+                        premiumPreviewBottomSheet.statusStickerSet = MessageObject.getInputStickerSet(document);
+                    }
+                    premiumPreviewBottomSheet.overrideTitleIcon = icon;
+                    premiumPreviewBottomSheet.isEmojiStatus = true;
+                }
+            }
+            showDialog(premiumPreviewBottomSheet);
+        }
+
         @Override
         public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY) {
             if (actionBar.isActionModeShowed() || reportType >= 0) {
@@ -30547,7 +30616,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
 
         private void openChat(ChatMessageCell cell, TLRPC.Chat chat, int postId) {
             if (currentChat != null && chat.id == currentChat.id) {
-                scrollToMessageId(postId, cell.getMessageObject().getId(), true, 0, true, 0);
+                if (avatarContainer != null && postId == 0) {
+                    avatarContainer.openProfile(false);
+                } else {
+                    scrollToMessageId(postId, cell.getMessageObject().getId(), true, 0, true, 0);
+                }
             } else if (currentChat == null || chat.id != currentChat.id || isThreadChat()) {
                 Bundle args = new Bundle();
                 args.putLong("chat_id", chat.id);
@@ -30847,16 +30920,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
         }
 
         @Override
-        public void didPressCode(ChatMessageCell cell, CharacterStyle _span, boolean longPress) {
-            if (!(_span instanceof CodeHighlighting.Span)) {
+        public void didPressCodeCopy(ChatMessageCell cell, MessageObject.TextLayoutBlock block) {
+            if (block == null || block.textLayout == null || block.textLayout.getText() == null) {
                 return;
             }
-            final CodeHighlighting.Span span = (CodeHighlighting.Span) _span;
-            SpannableStringBuilder text = new SpannableStringBuilder(span.code);
-            text.setSpan(new CodeHighlighting.Span(false, 0, null, span.lng, span.code), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-            AndroidUtilities.addToClipboard(text);
-            createUndoView();
-            undoView.showWithAction(0, UndoView.ACTION_TEXT_COPIED, null);
+
+            String string = block.textLayout.getText().toString();
+            SpannableString code = new SpannableString(string);
+            code.setSpan(new CodeHighlighting.Span(false, 0, null, block.language, string), 0, code.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            AndroidUtilities.addToClipboard(code);
+            BulletinFactory.of(ChatActivity.this).createCopyBulletin(LocaleController.getString(R.string.CodeCopied)).show();
         }
 
         @Override
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java
index 82979d6bc..506c3bf39 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java
@@ -376,7 +376,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
             if (slowmodeInfoRow == -1 && gigaHeaderRow == -1 || removedUsersRow != -1) {
                 participantsDividerRow = rowCount++;
             }
-            if (ChatObject.canBlockUsers(currentChat) && (ChatObject.isChannel(currentChat) || currentChat.creator)) {
+            if (ChatObject.canBlockUsers(currentChat) && getParticipantsCount() > 1 && (ChatObject.isChannel(currentChat) || currentChat.creator)) {
                 addNewRow = rowCount++;
             }
 
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java
index 85931eec6..489e53d30 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java
@@ -23,6 +23,7 @@ import android.graphics.Shader;
 import android.graphics.drawable.Animatable;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.Build;
+import android.util.Log;
 import android.view.View;
 
 import org.telegram.messenger.AndroidUtilities;
@@ -32,6 +33,7 @@ import org.telegram.messenger.DispatchQueue;
 import org.telegram.messenger.DispatchQueuePoolBackground;
 import org.telegram.messenger.FileLoader;
 import org.telegram.messenger.FileLog;
+import org.telegram.messenger.ImageLoader;
 import org.telegram.messenger.ImageLocation;
 import org.telegram.messenger.ImageReceiver;
 import org.telegram.messenger.SharedConfig;
@@ -353,6 +355,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
         }
     }
 
+    private int decoderTryCount = 0;
     private Runnable loadFrameRunnable = new Runnable() {
         @Override
         public void run() {
@@ -364,7 +367,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
                         nativePtr = 0;
                     }
                     updateScaleFactor();
-                    decoderCreated = true;
+                    decoderCreated = !isWebmSticker || nativePtr != 0 || (decoderTryCount++) > 15;
                 }
                 try {
                     if (bitmapsCache != null) {
@@ -1077,7 +1080,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
     }
 
     public boolean isRecycled() {
-        return isRecycled;
+        return isRecycled || decoderTryCount >= 15;
     }
 
     public Bitmap getNextFrame() {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFloat.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFloat.java
index f70b563b1..d0b595a9d 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFloat.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFloat.java
@@ -197,6 +197,10 @@ public class AnimatedFloat {
         }
     }
 
+    public float getTargetValue() {
+        return targetValue;
+    }
+
     public void setParent(View parent) {
         this.parent = parent;
     }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarConstructorFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarConstructorFragment.java
index f2a053486..e02b8cffd 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarConstructorFragment.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarConstructorFragment.java
@@ -10,6 +10,7 @@ import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.ColorFilter;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.PorterDuff;
@@ -400,7 +401,7 @@ public class AvatarConstructorFragment extends BaseFragment {
         chooseEmojiHint.setGravity(Gravity.CENTER);
         linearLayout.addView(chooseEmojiHint, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 21, 18, 21, 10));
 
-        selectAnimatedEmojiDialog = new SelectAnimatedEmojiDialog(this, getContext(), false, null, SelectAnimatedEmojiDialog.TYPE_AVATAR_CONSTRUCTOR, null) {
+        selectAnimatedEmojiDialog = new SelectAnimatedEmojiDialog(this, getContext(), false, null, SelectAnimatedEmojiDialog.TYPE_AVATAR_CONSTRUCTOR, true, null, 16, Theme.isCurrentThemeDark() ? Color.WHITE : getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon)) {
 
             private boolean firstLayout = true;
 
@@ -685,6 +686,7 @@ public class AvatarConstructorFragment extends BaseFragment {
         float changeBackgroundProgress = 1f;
         BackgroundGradient backgroundGradient;
 
+        private ColorFilter colorFilter = new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
         AnimatedFloat expandProgress = new AnimatedFloat(this, 200, CubicBezierInterpolator.EASE_OUT);
         boolean expanded;
         float overrideExpandProgress = -1f;
@@ -791,8 +793,8 @@ public class AvatarConstructorFragment extends BaseFragment {
                     backupImageView.animatedEmojiDrawable.getImageReceiver().setRoundRadius((int) (imageSize * 2 * STICKER_DEFAULT_ROUND_RADIUS));
                 }
                 backupImageView.animatedEmojiDrawable.setBounds((int) (cx - imageSize), (int) (cy - imageSize), (int) (cx + imageSize), (int) (cy + imageSize));
+                backupImageView.animatedEmojiDrawable.setColorFilter(colorFilter);
                 backupImageView.animatedEmojiDrawable.draw(canvas);
-
             } else {
                 backupImageView.imageReceiver.setImageCoords(cx - imageSize, cy - imageSize, imageSize * 2, imageSize * 2);
                 backupImageView.imageReceiver.setRoundRadius((int) (imageSize * 2 * STICKER_DEFAULT_ROUND_RADIUS));
@@ -842,6 +844,9 @@ public class AvatarConstructorFragment extends BaseFragment {
             ImageReceiver imageReceiver = backupImageView.getImageReceiver();
             if (backupImageView.animatedEmojiDrawable != null) {
                 imageReceiver = backupImageView.animatedEmojiDrawable.getImageReceiver();
+                if (imageReceiver != null) {
+                    imageReceiver.setColorFilter(colorFilter);
+                }
             }
             return imageReceiver;
         }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotCommandsMenuView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotCommandsMenuView.java
index 1641c1690..2a9725307 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotCommandsMenuView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotCommandsMenuView.java
@@ -320,7 +320,7 @@ public class BotCommandsMenuView extends View {
         public BotCommandView(@NonNull Context context) {
             super(context);
             setOrientation(HORIZONTAL);
-            setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0);
+            setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(8), AndroidUtilities.dp(16), AndroidUtilities.dp(8));
 
             description = new TextView(context) {
                 @Override
@@ -333,7 +333,7 @@ public class BotCommandsMenuView extends View {
             description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
             description.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
             description.setTag(Theme.key_windowBackgroundWhiteBlackText);
-            description.setLines(1);
+            description.setMaxLines(2);
             description.setEllipsize(TextUtils.TruncateAt.END);
             addView(description, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 1f, Gravity.CENTER_VERTICAL, 0, 0, AndroidUtilities.dp(8), 0));
 
@@ -344,11 +344,6 @@ public class BotCommandsMenuView extends View {
             addView(command, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0f, Gravity.CENTER_VERTICAL));
         }
 
-        @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(36), MeasureSpec.EXACTLY));
-        }
-
         public String getCommand() {
             return commandStr;
         }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewSheet.java
index ac8df8d1a..1f601fdcd 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewSheet.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewSheet.java
@@ -847,7 +847,8 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
     public static JSONObject makeThemeParams(Theme.ResourcesProvider resourcesProvider) {
         try {
             JSONObject jsonObject = new JSONObject();
-            jsonObject.put("bg_color", Theme.getColor(Theme.key_dialogBackground, resourcesProvider));
+            final int backgroundColor = Theme.getColor(Theme.key_dialogBackground, resourcesProvider);
+            jsonObject.put("bg_color", backgroundColor);
             jsonObject.put("section_bg_color", Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider));
             jsonObject.put("secondary_bg_color", Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider));
             jsonObject.put("text_color", Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
@@ -856,10 +857,10 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi
             jsonObject.put("button_color", Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider));
             jsonObject.put("button_text_color", Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider));
             jsonObject.put("header_bg_color", Theme.getColor(Theme.key_actionBarDefault, resourcesProvider));
-            jsonObject.put("accent_text_color", Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4, resourcesProvider));
-            jsonObject.put("section_header_text_color", Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader, resourcesProvider));
-            jsonObject.put("subtitle_text_color", Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider));
-            jsonObject.put("destructive_text_color", Theme.getColor(Theme.key_text_RedRegular, resourcesProvider));
+            jsonObject.put("accent_text_color", Theme.blendOver(backgroundColor, Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4, resourcesProvider)));
+            jsonObject.put("section_header_text_color", Theme.blendOver(backgroundColor, Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader, resourcesProvider)));
+            jsonObject.put("subtitle_text_color", Theme.blendOver(backgroundColor, Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)));
+            jsonObject.put("destructive_text_color", Theme.blendOver(backgroundColor, Theme.getColor(Theme.key_text_RedRegular, resourcesProvider)));
             return jsonObject;
         } catch (Exception e) {
             FileLog.e(e);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java
index e28b9beb8..2055dc774 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java
@@ -2590,7 +2590,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
         containerView.addView(writeButtonContainer, LayoutHelper.createFrame(60, 60, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 6, 10));
 
         writeButton = new ImageView(context);
-        writeButtonDrawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), getThemedColor(Theme.key_dialogFloatingButton), getThemedColor(Build.VERSION.SDK_INT >= 21 ? Theme.key_dialogFloatingButtonPressed : Theme.key_dialogFloatingButton));
+        writeButtonDrawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), getThemedColor(Theme.key_chat_attachCheckBoxBackground), getThemedColor(Build.VERSION.SDK_INT >= 21 ? Theme.key_dialogFloatingButtonPressed : Theme.key_chat_attachCheckBoxBackground));
         if (Build.VERSION.SDK_INT < 21) {
             Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow_profile).mutate();
             shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY));
@@ -2779,7 +2779,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
                 rect.set(cx - size / 2, 0, cx + size / 2, getMeasuredHeight());
                 canvas.drawRoundRect(rect, AndroidUtilities.dp(12), AndroidUtilities.dp(12), paint);
 
-                paint.setColor(getThemedColor(Theme.key_dialogRoundCheckBox));
+                paint.setColor(getThemedColor(Theme.key_chat_attachCheckBoxBackground));
                 rect.set(cx - size / 2 + AndroidUtilities.dp(2), AndroidUtilities.dp(2), cx + size / 2 - AndroidUtilities.dp(2), getMeasuredHeight() - AndroidUtilities.dp(2));
                 canvas.drawRoundRect(rect, AndroidUtilities.dp(10), AndroidUtilities.dp(10), paint);
 
@@ -3713,8 +3713,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
             }
         }
 
-        Theme.setSelectorDrawableColor(writeButtonDrawable, getThemedColor(Theme.key_dialogFloatingButton), false);
-        Theme.setSelectorDrawableColor(writeButtonDrawable, getThemedColor(Build.VERSION.SDK_INT >= 21 ? Theme.key_dialogFloatingButtonPressed : Theme.key_dialogFloatingButton), true);
+        Theme.setSelectorDrawableColor(writeButtonDrawable, getThemedColor(Theme.key_chat_attachCheckBoxBackground), false);
+        Theme.setSelectorDrawableColor(writeButtonDrawable, getThemedColor(Build.VERSION.SDK_INT >= 21 ? Theme.key_dialogFloatingButtonPressed : Theme.key_chat_attachCheckBoxBackground), true);
         writeButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.MULTIPLY));
 
         actionBarShadow.setBackgroundColor(getThemedColor(Theme.key_dialogShadowLine));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java
index 9598bd776..f70bcc6fd 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java
@@ -1441,6 +1441,10 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
                     boolean isAnimatedSticker = MessageObject.isAnimatedStickerDocument(document, true);
                     mediaEntity.subType |= isAnimatedSticker ? 1 : 4;
                 }
+                if (MessageObject.isTextColorEmoji(document)) {
+                    mediaEntity.color = 0xFFFFFFFF;
+                    mediaEntity.subType |= 8;
+                }
 
                 photoEntry.editedInfo.mediaEntities = new ArrayList<>();
                 photoEntry.editedInfo.mediaEntities.add(mediaEntity);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java
index f47911c22..242a487a6 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java
@@ -863,12 +863,12 @@ public class EditTextBoldCursor extends EditTextEffects {
                 throw new RuntimeException(e);
             }
         }
-        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT_WATCH) {
+        if (!EditTextEffects.allowHackingTextCanvas()) {
             ignoreTopCount = 1;
             ignoreBottomCount = 1;
         }
         canvas.save();
-        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT_WATCH) {
+        if (!EditTextEffects.allowHackingTextCanvas()) {
             canvas.translate(0, topPadding);
         }
         try {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java
index d5c225dcc..d8688f2d6 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java
@@ -271,7 +271,19 @@ public class EditTextEffects extends EditText {
         return offsetY;
     }
 
-    public boolean wrapCanvasToFixClipping = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH;
+    private static Boolean allowHackingTextCanvasCache;
+    public static boolean allowHackingTextCanvas() {
+        if (allowHackingTextCanvasCache == null) {
+            allowHackingTextCanvasCache = Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH && (
+                Build.MANUFACTURER == null ||
+                !Build.MANUFACTURER.equalsIgnoreCase("HONOR") &&
+                !Build.MANUFACTURER.equalsIgnoreCase("HUAWEI")
+            );
+        }
+        return allowHackingTextCanvasCache;
+    }
+
+    public boolean wrapCanvasToFixClipping = allowHackingTextCanvas();
     private NoClipCanvas wrappedCanvas;
 
     @Override
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java
index 9c5ea7617..2b7c472d6 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java
@@ -563,6 +563,10 @@ public class LinkSpanDrawable {
             return null;
         }
 
+        public int overrideColor() {
+            return Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider);
+        }
+
         @Override
         public boolean onTouchEvent(MotionEvent event) {
             if (links != null) {
@@ -571,6 +575,7 @@ public class LinkSpanDrawable {
                 if ((span = hit((int) event.getX(), (int) event.getY())) != null) {
                     if (event.getAction() == MotionEvent.ACTION_DOWN) {
                         final LinkSpanDrawable link = new LinkSpanDrawable(span, resourcesProvider, event.getX(), event.getY());
+                        link.setColor(overrideColor());
                         pressedLink = link;
                         links.addLink(pressedLink);
                         Spannable buffer = new SpannableString(textLayout.getText());
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/NoClipCanvas.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NoClipCanvas.java
index e092330ed..8e6674fc5 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NoClipCanvas.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NoClipCanvas.java
@@ -613,4 +613,15 @@ public class NoClipCanvas extends Canvas {
     public boolean quickReject(float left, float top, float right, float bottom, @NonNull EdgeType type) {
         return canvas.quickReject(left, top, right, bottom, type);
     }
+
+    @Override
+    public void concat(@Nullable Matrix matrix) {
+        canvas.concat(matrix);
+    }
+
+    @Override
+    public boolean isOpaque() {
+        return canvas.isOpaque();
+    }
+
 }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java
index d5dfeea33..3c6b797b7 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java
@@ -770,8 +770,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView imp
             canApplyBoost.setMyBoosts(myBoosts);
             onBoostSuccess();
 
-            String str = LocaleController.formatString("BoostingReassignedFrom", R.string.BoostingReassignedFrom,
-                    LocaleController.formatPluralString("BoostingSubscriptionsCount", size),
+            String str = LocaleController.formatPluralString("BoostingReassignedFromPlural", size,
                     LocaleController.formatPluralString("BoostingFromOtherChannel", channels));
             BulletinFactory bulletinFactory = BulletinFactory.of(container, resourcesProvider);
             bulletinFactory.createSimpleBulletinWithIconSize(R.raw.forward, str, 30).setDuration(4000).show(true);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java
index 67f436e03..f1150a566 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java
@@ -33,6 +33,7 @@ import androidx.recyclerview.widget.RecyclerView;
 
 import org.telegram.messenger.AndroidUtilities;
 import org.telegram.messenger.ContactsController;
+import org.telegram.messenger.Emoji;
 import org.telegram.messenger.LocaleController;
 import org.telegram.messenger.MediaDataController;
 import org.telegram.messenger.NotificationCenter;
@@ -43,6 +44,7 @@ import org.telegram.tgnet.TLRPC;
 import org.telegram.ui.ActionBar.BaseFragment;
 import org.telegram.ui.ActionBar.SimpleTextView;
 import org.telegram.ui.ActionBar.Theme;
+import org.telegram.ui.Cells.ChatMessageCell;
 import org.telegram.ui.Cells.ShadowSectionCell;
 import org.telegram.ui.Components.AnimatedEmojiDrawable;
 import org.telegram.ui.Components.AnimatedEmojiSpan;
@@ -87,12 +89,13 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
     ViewGroup iconContainer;
     BaseFragment fragment;
 
+    public Integer accentColor;
     public float startEnterFromX;
     public float startEnterFromY;
     public float startEnterFromX1;
     public float startEnterFromY1;
     public float startEnterFromScale;
-    public SimpleTextView startEnterFromView;
+    public View startEnterFromView;
     public View overrideTitleIcon;
     public TLRPC.InputStickerSet statusStickerSet;
     public boolean isEmojiStatus;
@@ -265,7 +268,10 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
         if (statusStickerSet != null) {
             final String stickerSetPlaceholder = "";
             String string = LocaleController.formatString(R.string.TelegramPremiumUserStatusDialogTitle, ContactsController.formatName(user.first_name, user.last_name), stickerSetPlaceholder);
-            CharSequence charSequence = AndroidUtilities.replaceSingleTag(string, Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null);
+            CharSequence charSequence = AndroidUtilities.replaceSingleLink(string, accentColor == null ? getThemedColor(Theme.key_windowBackgroundWhiteBlueButton) : accentColor);
+            try {
+                charSequence = Emoji.replaceEmoji(charSequence, titleView[0].getPaint().getFontMetricsInt(), false);
+            } catch (Exception ignore) {}
             SpannableStringBuilder title = charSequence instanceof SpannableStringBuilder ? ((SpannableStringBuilder) charSequence) : new SpannableStringBuilder(charSequence);
             int index = charSequence.toString().indexOf(stickerSetPlaceholder);
             if (index >= 0) {
@@ -301,6 +307,9 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
                     public void updateDrawState(@NonNull TextPaint ds) {
                         super.updateDrawState(ds);
                         ds.setUnderlineText(false);
+                        if (accentColor != null) {
+                            ds.setColor(accentColor);
+                        }
                     }
                     @Override
                     public void onClick(@NonNull View view) {}
@@ -356,24 +365,27 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
             subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.TelegramPremiumUserStatusDialogSubtitle, ContactsController.formatName(user.first_name, user.last_name))));
         } else if (giftTier != null) {
             if (isOutboundGift) {
-                titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton,  AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
-                subtitleView.setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogSubtitle, user != null ? user.first_name : ""), Theme.key_windowBackgroundWhiteBlueButton,  AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
+                titleView[0].setText(AndroidUtilities.replaceSingleLink(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), accentColor == null ? getThemedColor(Theme.key_windowBackgroundWhiteBlueButton) : accentColor));
+                subtitleView.setText(AndroidUtilities.replaceSingleLink(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogSubtitle, user != null ? user.first_name : ""), accentColor == null ? getThemedColor(Theme.key_windowBackgroundWhiteBlueButton) : accentColor));
             } else if (user == null || TextUtils.isEmpty(user.first_name) || user.id == 777000) {
-                titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPluralSomeone, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton,  AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
+                titleView[0].setText(AndroidUtilities.replaceSingleLink(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPluralSomeone, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), accentColor == null ? getThemedColor(Theme.key_windowBackgroundWhiteBlueButton) : accentColor));
                 subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle)));
             } else {
-                titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPlural, user.first_name, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton,  AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
+                titleView[0].setText(AndroidUtilities.replaceSingleLink(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPlural, user.first_name, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), accentColor == null ? getThemedColor(Theme.key_windowBackgroundWhiteBlueButton) : accentColor));
                 subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle)));
             }
         } else {
-            if(user == null) {
+            if (user == null) {
                 titleView[0].setText(LocaleController.getString(R.string.TelegramPremium));
                 subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumSubscribedSubtitle)));
             } else {
-                titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserDialogTitle, ContactsController.formatName(user.first_name, user.last_name)), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
+                titleView[0].setText(AndroidUtilities.replaceSingleLink(LocaleController.formatString(R.string.TelegramPremiumUserDialogTitle, ContactsController.formatName(user.first_name, user.last_name)), accentColor == null ? getThemedColor(Theme.key_windowBackgroundWhiteBlueButton) : accentColor));
                 subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserDialogSubtitle)));
             }
         }
+        try {
+            titleView[0].setText(Emoji.replaceEmoji(titleView[0].getText(), titleView[0].getPaint().getFontMetricsInt(), false));
+        } catch (Exception ignore) {}
     }
 
     @Override
@@ -439,7 +451,7 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
                         titleViewContainer = new FrameLayout(context);
                         titleViewContainer.setClipChildren(false);
 
-                        final ColorFilter colorFilter = new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon), PorterDuff.Mode.SRC_IN);
+                        final ColorFilter colorFilter = new PorterDuffColorFilter(accentColor == null ? getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon) : accentColor, PorterDuff.Mode.SRC_IN);
                         titleView = new LinkSpanDrawable.LinksTextView[2];
                         for (int a = 0; a < 2; ++a) {
                             titleView[a] = new LinkSpanDrawable.LinksTextView(context, resourcesProvider) {
@@ -466,6 +478,11 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
                                 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                                     super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(99999999, MeasureSpec.AT_MOST));
                                 }
+
+                                @Override
+                                public int overrideColor() {
+                                    return accentColor != null ? Theme.multAlpha(accentColor, .10f) : super.overrideColor();
+                                }
                             };
                             titleView[a].setVisibility(a == 0 ? View.VISIBLE : View.GONE);
                             titleView[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
@@ -651,7 +668,16 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
 
             float[] points = new float[]{startEnterFromX, startEnterFromY};
             startEnterFromView.getMatrix().mapPoints(points);
-            Drawable startEnterFromDrawable = startEnterFromView.getRightDrawable();
+            Drawable startEnterFromDrawable = null;
+            if (startEnterFromView instanceof SimpleTextView) {
+                startEnterFromDrawable = ((SimpleTextView) startEnterFromView).getRightDrawable();
+            } else if (startEnterFromView instanceof ChatMessageCell) {
+                startEnterFromDrawable = ((ChatMessageCell) startEnterFromView).currentNameStatusDrawable;
+            }
+            if (startEnterFromDrawable == null) {
+                canvas.restore();
+                return;
+            }
             float cxFrom = -coords[0] + startEnterFromX1 + points[0];
             float cyFrom = -coords[1] + startEnterFromY1 + points[1];
 
@@ -715,8 +741,23 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
         enterTransitionProgress = 0f;
         enterTransitionInProgress = true;
         iconContainer.invalidate();
-        startEnterFromView.getRightDrawable().setAlpha(0);
-        startEnterFromView.invalidate();
+        final Drawable startEnterFromDrawable;
+        if (startEnterFromView instanceof SimpleTextView) {
+            startEnterFromDrawable = ((SimpleTextView) startEnterFromView).getRightDrawable();
+        } else if (startEnterFromView instanceof ChatMessageCell) {
+            startEnterFromDrawable = ((ChatMessageCell) startEnterFromView).currentNameStatusDrawable;
+            ((ChatMessageCell) startEnterFromView).invalidateOutbounds();
+        } else {
+            startEnterFromDrawable = null;
+        }
+        if (startEnterFromDrawable != null) {
+            startEnterFromDrawable.setAlpha(0);
+        }
+        if (startEnterFromView instanceof ChatMessageCell) {
+            ((ChatMessageCell) startEnterFromView).invalidateOutbounds();
+        } else {
+            startEnterFromView.invalidate();
+        }
         if (iconTextureView != null) {
             iconTextureView.startEnterAnimation(-360, 100);
         }
@@ -730,13 +771,18 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
                 enterTransitionInProgress = false;
                 enterTransitionProgress = 1f;
                 iconContainer.invalidate();
-                ValueAnimator iconAlphaBack = ValueAnimator.ofInt(0, 255);
-                Drawable drawable = startEnterFromView.getRightDrawable();
-                iconAlphaBack.addUpdateListener(animation1 -> {
-                    drawable.setAlpha((Integer) animation1.getAnimatedValue());
-                    startEnterFromView.invalidate();
-                });
-                iconAlphaBack.start();
+                if (startEnterFromDrawable != null) {
+                    ValueAnimator iconAlphaBack = ValueAnimator.ofInt(0, 255);
+                    iconAlphaBack.addUpdateListener(animation1 -> {
+                        startEnterFromDrawable.setAlpha((Integer) animation1.getAnimatedValue());
+                        if (startEnterFromView instanceof ChatMessageCell) {
+                            ((ChatMessageCell) startEnterFromView).invalidateOutbounds();
+                        } else {
+                            startEnterFromView.invalidate();
+                        }
+                    });
+                    iconAlphaBack.start();
+                }
                 super.onAnimationEnd(animation);
             }
         });
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostCounterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostCounterView.java
index 16f93e85c..04019e1a1 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostCounterView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostCounterView.java
@@ -39,7 +39,7 @@ public class BoostCounterView extends View {
         countText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
         countText.setTextColor(Color.WHITE);
         countText.setText("");
-        countText.setGravity(Gravity.CENTER_HORIZONTAL);
+        countText.setGravity(Gravity.CENTER);
 
         bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         bgPaint.setColor(0xFF967bff);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostDialogs.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostDialogs.java
index 77a60a586..d08db75a1 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostDialogs.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostDialogs.java
@@ -429,7 +429,7 @@ public class BoostDialogs {
 
             AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider);
             builder.setTitle(getString("BoostingReduceQuantity", R.string.BoostingReduceQuantity));
-            builder.setMessage(replaceTags(formatString("BoostingReduceUsersText", R.string.BoostingReduceUsersText, current, downTo)));
+            builder.setMessage(replaceTags(formatPluralString("BoostingReduceUsersTextPlural", current, downTo)));
             builder.setPositiveButton(getString("OK", R.string.OK), (dialogInterface, i) -> {
 
             });
@@ -439,11 +439,11 @@ public class BoostDialogs {
         return false;
     }
 
-    public static boolean checkReduceQuantity(Context context, Theme.ResourcesProvider resourcesProvider, List list, TLRPC.TL_premiumGiftCodeOption selected, Utilities.Callback onSuccess) {
+    public static boolean checkReduceQuantity(List sliderValues, Context context, Theme.ResourcesProvider resourcesProvider, List list, TLRPC.TL_premiumGiftCodeOption selected, Utilities.Callback onSuccess) {
         if (selected.store_product == null) {
             List result = new ArrayList<>();
             for (TLRPC.TL_premiumGiftCodeOption item : list) {
-                if (item.months == selected.months && item.store_product != null) {
+                if (item.months == selected.months && item.store_product != null && sliderValues.contains(item.users)) {
                     result.add(item);
                 }
             }
@@ -462,7 +462,7 @@ public class BoostDialogs {
             int downTo = suggestion.users;
             AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider);
             builder.setTitle(getString("BoostingReduceQuantity", R.string.BoostingReduceQuantity));
-            builder.setMessage(replaceTags(formatString("BoostingReduceQuantityText", R.string.BoostingReduceQuantityText, current, months, downTo)));
+            builder.setMessage(replaceTags(formatPluralString("BoostingReduceQuantityTextPlural", current, months, downTo)));
             builder.setPositiveButton(getString("Reduce", R.string.Reduce), (dialogInterface, i) -> onSuccess.run(finalSuggestion));
             builder.setNegativeButton(getString("Cancel", R.string.Cancel), (dialogInterface, i) -> {
 
@@ -473,9 +473,7 @@ public class BoostDialogs {
         return false;
     }
 
-    public static void showAbout(long chatId, long msgDate, TLRPC.TL_payments_giveawayInfo giveawayInfo, TLRPC.TL_messageMediaGiveaway giveaway, Context context, Theme.ResourcesProvider resourcesProvider) {
-        TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-chatId);
-        String from = chat != null ? chat.title : "";
+    public static void showAbout(String from, long msgDate, TLRPC.TL_payments_giveawayInfo giveawayInfo, TLRPC.TL_messageMediaGiveaway giveaway, Context context, Theme.ResourcesProvider resourcesProvider) {
         int quantity = giveaway.quantity;
         String months = formatPluralString("BoldMonths", giveaway.months);
         String endDate = LocaleController.getInstance().formatterGiveawayMonthDay.format(new Date(giveaway.until_date * 1000L));
@@ -492,13 +490,15 @@ public class BoostDialogs {
 
         if (giveaway.only_new_subscribers) {
             if (isSeveralChats) {
-                stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextDateSeveral", quantity, endDate, quantity, from, giveaway.channels.size() - 1, fromTime, fromDate)));
+                String andStr = formatPluralString("BoostingGiveawayHowItWorksSubTextDateSeveral2", giveaway.channels.size() - 1, fromTime, fromDate);
+                stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextDateSeveral1", quantity, endDate, quantity, from, andStr)));
             } else {
                 stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextDate", quantity, endDate, quantity, from, fromTime, fromDate)));
             }
         } else {
             if (isSeveralChats) {
-                stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextSeveral", quantity, endDate, quantity, from, giveaway.channels.size() - 1)));
+                String andStr = formatPluralString("BoostingGiveawayHowItWorksSubTextSeveral2", giveaway.channels.size() - 1);
+                stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextSeveral1", quantity, endDate, quantity, from, andStr)));
             } else {
                 stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubText", quantity, endDate, quantity, from)));
             }
@@ -508,7 +508,7 @@ public class BoostDialogs {
 
         if (giveawayInfo.participating) {
             if (isSeveralChats) {
-                stringBuilder.append(replaceTags(formatString("BoostingGiveawayParticipantMulti", R.string.BoostingGiveawayParticipantMulti, from, giveaway.channels.size() - 1)));
+                stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayParticipantMultiPlural", giveaway.channels.size() - 1, from)));
             } else {
                 stringBuilder.append(replaceTags(formatString("BoostingGiveawayParticipant", R.string.BoostingGiveawayParticipant, from)));
             }
@@ -523,7 +523,7 @@ public class BoostDialogs {
             stringBuilder.append(replaceTags(formatString("BoostingGiveawayNotEligible", R.string.BoostingGiveawayNotEligible, date)));
         } else {
             if (isSeveralChats) {
-                stringBuilder.append(replaceTags(formatString("BoostingGiveawayTakePartMulti", R.string.BoostingGiveawayTakePartMulti, from, giveaway.channels.size() - 1, endDate)));
+                stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayTakePartMultiPlural", giveaway.channels.size() - 1, from, endDate)));
             } else {
                 stringBuilder.append(replaceTags(formatString("BoostingGiveawayTakePart", R.string.BoostingGiveawayTakePart, from, endDate)));
             }
@@ -536,9 +536,7 @@ public class BoostDialogs {
         builder.show();
     }
 
-    public static void showAboutEnd(long chatId, long msgDate, TLRPC.TL_payments_giveawayInfoResults giveawayInfo, TLRPC.TL_messageMediaGiveaway giveaway, Context context, Theme.ResourcesProvider resourcesProvider) {
-        TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-chatId);
-        String from = chat != null ? chat.title : "";
+    public static void showAboutEnd(String from, long msgDate, TLRPC.TL_payments_giveawayInfoResults giveawayInfo, TLRPC.TL_messageMediaGiveaway giveaway, Context context, Theme.ResourcesProvider resourcesProvider) {
         int quantity = giveaway.quantity;
         String months = formatPluralString("BoldMonths", giveaway.months);
         String endDate = LocaleController.getInstance().formatterGiveawayMonthDay.format(new Date(giveaway.until_date * 1000L));
@@ -555,13 +553,15 @@ public class BoostDialogs {
 
         if (giveaway.only_new_subscribers) {
             if (isSeveralChats) {
-                stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextDateSeveralEnd", quantity, endDate, quantity, from, giveaway.channels.size() - 1, fromTime, fromDate)));
+                String andStr = formatPluralString("BoostingGiveawayHowItWorksSubTextDateSeveral2", giveaway.channels.size() - 1, fromTime, fromDate);
+                stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextDateSeveralEnd1", quantity, endDate, quantity, from, andStr)));
             } else {
                 stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextDateEnd", quantity, endDate, quantity, from, fromTime, fromDate)));
             }
         } else {
             if (isSeveralChats) {
-                stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextSeveralEnd", quantity, endDate, quantity, from, giveaway.channels.size() - 1)));
+                String andStr = formatPluralString("BoostingGiveawayHowItWorksSubTextSeveral2", giveaway.channels.size() - 1);
+                stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextSeveralEnd1", quantity, endDate, quantity, from, andStr)));
             } else {
                 stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextEnd", quantity, endDate, quantity, from)));
             }
@@ -583,7 +583,7 @@ public class BoostDialogs {
             bottomTextView.setText(str);
             bottomTextView.setTextColor(Theme.getColor(Theme.key_text_RedRegular, resourcesProvider));
             bottomTextView.setBackground(Theme.createRoundRectDrawable(dp(10), dp(10), Theme.multAlpha(Theme.getColor(Theme.key_text_RedRegular, resourcesProvider), 0.1f)));
-            bottomTextView.setPadding(0, dp(12), 0, dp(12));
+            bottomTextView.setPadding(dp(8), dp(12), dp(8), dp(12));
             builder.addBottomView(bottomTextView);
             builder.setMessage(stringBuilder);
             builder.setPositiveButton(getString("Close", R.string.Close), (dialogInterface, i) -> {
@@ -639,7 +639,7 @@ public class BoostDialogs {
         progress.init();
         progress.onCancel(() -> isCanceled.set(true));
         final TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media;
-        final long chatId = messageObject.getFromChatId();
+        final String fromName = getGiveawayCreatorName(messageObject);
         final long msgDate = messageObject.messageOwner.date * 1000L;
         BoostRepository.getGiveawayInfo(messageObject, result -> {
             if (isCanceled.get()) {
@@ -648,10 +648,10 @@ public class BoostDialogs {
             progress.end();
             if (result instanceof TLRPC.TL_payments_giveawayInfo) {
                 TLRPC.TL_payments_giveawayInfo giveawayInfo = (TLRPC.TL_payments_giveawayInfo) result;
-                showAbout(chatId, msgDate, giveawayInfo, giveaway, context, resourcesProvider);
+                showAbout(fromName, msgDate, giveawayInfo, giveaway, context, resourcesProvider);
             } else if (result instanceof TLRPC.TL_payments_giveawayInfoResults) {
                 TLRPC.TL_payments_giveawayInfoResults giveawayInfoResults = (TLRPC.TL_payments_giveawayInfoResults) result;
-                showAboutEnd(chatId, msgDate, giveawayInfoResults, giveaway, context, resourcesProvider);
+                showAboutEnd(fromName, msgDate, giveawayInfoResults, giveaway, context, resourcesProvider);
             }
         }, error -> {
             if (isCanceled.get()) {
@@ -661,18 +661,34 @@ public class BoostDialogs {
         });
     }
 
+    private static String getGiveawayCreatorName(MessageObject messageObject) {
+        if (messageObject == null) {
+            return "";
+        }
+        String forwardedName = messageObject.getForwardedName();
+        final String name;
+        if (forwardedName == null) {
+            final long chatId = messageObject.getFromChatId();
+            TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-chatId);
+            name = chat != null ? chat.title : "";
+        } else {
+            name = forwardedName;
+        }
+        return name;
+    }
+
     public static void showBulletinAbout(MessageObject messageObject) {
         if (messageObject == null) {
             return;
         }
         BoostRepository.getGiveawayInfo(messageObject, result -> {
             final TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media;
-            final long chatId = messageObject.getFromChatId();
             final long msgDate = messageObject.messageOwner.date * 1000L;
             BaseFragment fragment = LaunchActivity.getLastFragment();
             if (fragment == null) {
                 return;
             }
+            final String fromName = getGiveawayCreatorName(messageObject);
             final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), fragment.getResourceProvider());
 
             if (result instanceof TLRPC.TL_payments_giveawayInfoResults) {
@@ -697,10 +713,10 @@ public class BoostDialogs {
                     .setUndoAction(() -> {
                         if (result instanceof TLRPC.TL_payments_giveawayInfo) {
                             TLRPC.TL_payments_giveawayInfo giveawayInfo = (TLRPC.TL_payments_giveawayInfo) result;
-                            showAbout(chatId, msgDate, giveawayInfo, giveaway, fragment.getParentActivity(), fragment.getResourceProvider());
+                            showAbout(fromName, msgDate, giveawayInfo, giveaway, fragment.getParentActivity(), fragment.getResourceProvider());
                         } else if (result instanceof TLRPC.TL_payments_giveawayInfoResults) {
                             TLRPC.TL_payments_giveawayInfoResults giveawayInfoResults = (TLRPC.TL_payments_giveawayInfoResults) result;
-                            showAboutEnd(chatId, msgDate, giveawayInfoResults, giveaway, fragment.getParentActivity(), fragment.getResourceProvider());
+                            showAboutEnd(fromName, msgDate, giveawayInfoResults, giveaway, fragment.getParentActivity(), fragment.getResourceProvider());
                         }
                     }));
             Bulletin.make(fragment, layout, Bulletin.DURATION_LONG).show();
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostPagerBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostPagerBottomSheet.java
index b1da6f092..2977b6433 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostPagerBottomSheet.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostPagerBottomSheet.java
@@ -143,6 +143,14 @@ public class BoostPagerBottomSheet extends BottomSheet {
                 }
             }
 
+            @Override
+            protected float getAvailableTranslationX() {
+                if (isTablet || isLandscapeOrientation) {
+                    return getMeasuredWidth();
+                }
+                return super.getAvailableTranslationX();
+            }
+
             @Override
             protected boolean canScroll(MotionEvent e) {
                 return viewPager.getCurrentPosition() == 1;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostRepository.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostRepository.java
index e4a7198ed..54e68c61b 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostRepository.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostRepository.java
@@ -21,6 +21,7 @@ import org.telegram.messenger.MessagesController;
 import org.telegram.messenger.MessagesStorage;
 import org.telegram.messenger.SharedConfig;
 import org.telegram.messenger.UserConfig;
+import org.telegram.messenger.UserObject;
 import org.telegram.messenger.Utilities;
 import org.telegram.tgnet.ConnectionsManager;
 import org.telegram.tgnet.TLObject;
@@ -432,6 +433,9 @@ public class BoostRepository {
 
                 for (int i = 0; i < help_countriesList.countries.size(); i++) {
                     TLRPC.TL_help_country country = help_countriesList.countries.get(i);
+                    if (country.name != null) {
+                        country.default_name = country.name;
+                    }
                     if (country.iso2.equalsIgnoreCase("FT")) {
                         continue;
                     }
@@ -550,7 +554,10 @@ public class BoostRepository {
                 for (int a = 0; a < res.participants.size(); a++) {
                     TLRPC.Peer peer = res.participants.get(a).peer;
                     if (MessageObject.getPeerId(peer) != selfId) {
-                        result.add(controller.getInputPeer(peer));
+                        TLRPC.User user = controller.getUser(peer.user_id);
+                        if (user != null && !UserObject.isDeleted(user) && !user.bot) {
+                            result.add(controller.getInputPeer(peer));
+                        }
                     }
                 }
                 onDone.run(result);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostViaGiftsBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostViaGiftsBottomSheet.java
index 8e34fa980..b4ad98c10 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostViaGiftsBottomSheet.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostViaGiftsBottomSheet.java
@@ -117,6 +117,7 @@ public class BoostViaGiftsBottomSheet extends BottomSheetWithRecyclerListView im
                     }
                 }
                 selectedParticipantsType = tmpParticipantsType;
+                updateRows(false, false);
             } else if (view instanceof DurationCell) {
                 selectedMonths = ((TLRPC.TL_premiumGiftCodeOption) ((DurationCell) view).getGifCode()).months;
                 updateRows(false, false);
@@ -185,7 +186,7 @@ public class BoostViaGiftsBottomSheet extends BottomSheetWithRecyclerListView im
                     for (int i = 0; i < options.size(); i++) {
                         TLRPC.TL_premiumGiftCodeOption option = options.get(i);
                         if (option.months == selectedMonths) {
-                            if (BoostRepository.isGoogleBillingAvailable() && BoostDialogs.checkReduceQuantity(getContext(), resourcesProvider, giftCodeOptions, option, arg -> {
+                            if (BoostRepository.isGoogleBillingAvailable() && BoostDialogs.checkReduceQuantity(sliderValues, getContext(), resourcesProvider, giftCodeOptions, option, arg -> {
                                 selectedSliderIndex = sliderValues.indexOf(arg.users);
                                 updateRows(true, true);
                                 updateActionButton(true);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/GiftInfoBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/GiftInfoBottomSheet.java
index 8eb2aca2e..119a2625e 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/GiftInfoBottomSheet.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/GiftInfoBottomSheet.java
@@ -29,6 +29,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
 public class GiftInfoBottomSheet extends BottomSheetWithRecyclerListView {
 
     public static void show(BaseFragment fragment, String slug, Browser.Progress progress) {
+        if (fragment == null) {
+            return;
+        }
         final AtomicBoolean isCanceled = new AtomicBoolean(false);
         if (progress != null) {
             progress.init();
@@ -38,12 +41,11 @@ public class GiftInfoBottomSheet extends BottomSheetWithRecyclerListView {
             if (isCanceled.get()) {
                 return;
             }
-            GiftInfoBottomSheet alert = new GiftInfoBottomSheet(fragment, false, true, giftCode, slug);
-            if (fragment != null && fragment.getParentActivity() != null) {
-                fragment.showDialog(alert);
-            } else {
-                alert.show();
+            if (fragment.getParentActivity() == null) {
+                return;
             }
+            GiftInfoBottomSheet alert = new GiftInfoBottomSheet(fragment, false, true, giftCode, slug);
+            fragment.showDialog(alert);
             if (progress != null) {
                 progress.end();
             }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/ReassignBoostBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/ReassignBoostBottomSheet.java
index 01ab8b38c..991cc28ce 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/ReassignBoostBottomSheet.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/ReassignBoostBottomSheet.java
@@ -158,7 +158,7 @@ public class ReassignBoostBottomSheet extends BottomSheetWithRecyclerListView {
             if (view instanceof SelectorUserCell) {
                 SelectorUserCell cell = ((SelectorUserCell) view);
                 if (cell.getBoost().cooldown_until_date > 0) {
-                    SpannableStringBuilder text = AndroidUtilities.replaceTags(LocaleController.formatString("BoostingWaitWarning", R.string.BoostingWaitWarning, BoostRepository.boostsPerSentGift()));
+                    SpannableStringBuilder text = AndroidUtilities.replaceTags(LocaleController.formatPluralString("BoostingWaitWarningPlural", BoostRepository.boostsPerSentGift()));
                     BulletinFactory.of(container, resourcesProvider).createSimpleBulletin(R.raw.chats_infotip, text, 5).show(true);
                     return;
                 }
@@ -364,7 +364,7 @@ public class ReassignBoostBottomSheet extends BottomSheetWithRecyclerListView {
         }
 
         public void setData(TLRPC.Chat chat) {
-            description.setText(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingReassignBoostText", R.string.BoostingReassignBoostText, chat == null ? "" : chat.title, BoostRepository.boostsPerSentGift())));
+            description.setText(AndroidUtilities.replaceTags(LocaleController.formatPluralString("BoostingReassignBoostTextPlural", BoostRepository.boostsPerSentGift(), chat == null ? "" : chat.title)));
         }
 
         public void showBoosts(List selectedBoosts, TLRPC.Chat currentChat) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java
index 60d88c1f4..8ae9dba29 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java
@@ -276,7 +276,7 @@ public class SelectorBottomSheet extends BottomSheetWithRecyclerListView {
             linearSmoothScroller.setOffset(AndroidUtilities.dp(38));
             recyclerListView.getLayoutManager().startSmoothScroll(linearSmoothScroller);
         } else {
-            recyclerListView.scrollToPosition(1);
+            recyclerListView.scrollToPosition(0);
         }
     }
 
@@ -409,13 +409,14 @@ public class SelectorBottomSheet extends BottomSheetWithRecyclerListView {
         updateList(false, true);
         headerView.setText(getTitle());
         updateActionButton(false);
+        scrollToTop(false);
     }
 
     private void updateSection() {
         String text;
         switch (type) {
             case TYPE_CHANNEL:
-                text = LocaleController.formatString("BoostingSelectUpTo", R.string.BoostingSelectUpTo, BoostRepository.giveawayAddPeersMax());
+                text = LocaleController.formatPluralString("BoostingSelectUpToPlural", (int) BoostRepository.giveawayAddPeersMax());
                 sectionCell.setLayerHeight(32);
                 break;
             case TYPE_USER:
@@ -423,7 +424,7 @@ public class SelectorBottomSheet extends BottomSheetWithRecyclerListView {
                 sectionCell.setLayerHeight(32);
                 break;
             case TYPE_COUNTRY:
-                text = LocaleController.formatString("BoostingSelectUpTo", R.string.BoostingSelectUpToCountries, BoostRepository.giveawayCountriesMax());
+                text = LocaleController.formatPluralString("BoostingSelectUpToCountriesPlural", (int) BoostRepository.giveawayCountriesMax());
                 sectionCell.setLayerHeight(1);
                 break;
             default:
@@ -436,13 +437,13 @@ public class SelectorBottomSheet extends BottomSheetWithRecyclerListView {
         String text = "";
         switch (type) {
             case TYPE_CHANNEL:
-                text = LocaleController.formatString("BoostingSelectUpToWarningChannels", R.string.BoostingSelectUpToWarningChannels, BoostRepository.giveawayAddPeersMax());
+                text = LocaleController.formatPluralString("BoostingSelectUpToWarningChannelsPlural", (int) BoostRepository.giveawayAddPeersMax());
                 break;
             case TYPE_USER:
                 text = LocaleController.getString("BoostingSelectUpToWarningUsers", R.string.BoostingSelectUpToWarningUsers);
                 break;
             case TYPE_COUNTRY:
-                text = LocaleController.formatString("BoostingSelectUpToWarningCountries", R.string.BoostingSelectUpToWarningCountries, BoostRepository.giveawayCountriesMax());
+                text = LocaleController.formatPluralString("BoostingSelectUpToWarningCountriesPlural", (int) BoostRepository.giveawayCountriesMax());
                 break;
         }
         if (selectedObjectsListener != null) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/GiftInfoAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/GiftInfoAdapter.java
index 68226d836..386348ff9 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/GiftInfoAdapter.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/GiftInfoAdapter.java
@@ -140,7 +140,7 @@ public abstract class GiftInfoAdapter extends RecyclerListView.SelectionAdapter
             case HOLDER_TYPE_LINK: {
                 LinkCell cell = (LinkCell) holder.itemView;
                 cell.setSlug(slug);
-                if (giftCode.boost != null) {
+                if (giftCode.boost != null && slug == null) {
                     cell.hideSlug(this::onHiddenLinkClicked);
                 }
                 //unclaimed and slug visible only for giveaway creator
@@ -230,7 +230,7 @@ public abstract class GiftInfoAdapter extends RecyclerListView.SelectionAdapter
                         dismiss();
                     }
                 });
-                if (giftCode.boost != null || giftCode.to_id == NO_USER_ID) {
+                if (giftCode.boost != null || giftCode.flags == -1) {
                     cell.setCloseStyle();
                     cell.setOnClickListener(v -> dismiss());
                 }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BoostTypeSingleCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BoostTypeSingleCell.java
index 5bbc92f80..13e5c8feb 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BoostTypeSingleCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BoostTypeSingleCell.java
@@ -25,7 +25,7 @@ public class BoostTypeSingleCell extends BoostTypeCell {
         subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider));
         avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_GIFT);
         titleTextView.setText(LocaleController.formatString("BoostingPreparedGiveawayOne", R.string.BoostingPreparedGiveawayOne));
-        String subtitle = LocaleController.formatString("BoostingPreparedGiveawaySubscriptions", R.string.BoostingPreparedGiveawaySubscriptions, prepaidGiveaway.quantity, LocaleController.formatPluralString("Months", prepaidGiveaway.months));
+        String subtitle = LocaleController.formatPluralString("BoostingPreparedGiveawaySubscriptionsPlural", prepaidGiveaway.quantity, LocaleController.formatPluralString("Months", prepaidGiveaway.months));
         setSubtitle(subtitle);
         if (prepaidGiveaway.months == 12) {
             avatarDrawable.setColor(0xFFff8560, 0xFFd55246);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/SubtitleWithCounterCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/SubtitleWithCounterCell.java
index cfc67861f..548149359 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/SubtitleWithCounterCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/SubtitleWithCounterCell.java
@@ -34,7 +34,7 @@ public class SubtitleWithCounterCell extends org.telegram.ui.Cells.HeaderCell {
     }
 
     public void updateCounter(boolean animated, int count) {
-        CharSequence text = LocaleController.formatPluralString("BoostingSubscriptionsCount", count, count);
+        CharSequence text = LocaleController.formatPluralString("BoostingBoostsCountTitle", count, count);
         counterTextView.setText(text, animated);
     }
 }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/msg/GiveawayMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/msg/GiveawayMessageCell.java
index 17ac9963b..6acfa288a 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/msg/GiveawayMessageCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/msg/GiveawayMessageCell.java
@@ -2,6 +2,8 @@ package org.telegram.ui.Components.Premium.boosts.cells.msg;
 
 import static org.telegram.messenger.AndroidUtilities.dp;
 import static org.telegram.messenger.AndroidUtilities.replaceTags;
+import static org.telegram.messenger.LocaleController.formatPluralString;
+import static org.telegram.messenger.LocaleController.formatPluralStringComma;
 import static org.telegram.messenger.LocaleController.formatString;
 import static org.telegram.messenger.LocaleController.getString;
 
@@ -71,10 +73,10 @@ public class GiveawayMessageCell {
     private final ChatMessageCell parentView;
     private final ImageReceiver giftReceiver;
 
-    private final CharSequence[] chatTitles = new CharSequence[10];
-    private final float[] chatTitleWidths = new float[10];
-    private final boolean[] needNewRow = new boolean[10];
-    private final Rect[] clickRect = new Rect[10];
+    private CharSequence[] chatTitles = new CharSequence[10];
+    private float[] chatTitleWidths = new float[10];
+    private boolean[] needNewRow = new boolean[10];
+    private Rect[] clickRect = new Rect[10];
     private boolean[] avatarVisible;
     private int measuredHeight = 0;
     private int measuredWidth = 0;
@@ -218,6 +220,7 @@ public class GiveawayMessageCell {
         createImages();
         setGiftImage(messageObject);
         TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media;
+        checkArraysLimits(giveaway.channels.size());
 
         int giftSize = AndroidUtilities.dp(148);
         int maxWidth;
@@ -231,8 +234,13 @@ public class GiveawayMessageCell {
         SpannableStringBuilder topStringBuilder = new SpannableStringBuilder(giveawayPrizes);
         topStringBuilder.setSpan(new RelativeSizeSpan(1.05f), 0, giveawayPrizes.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         topStringBuilder.append("\n");
-        CharSequence subTitle = replaceTags(formatString("BoostingGiveawayMsgInfo", R.string.BoostingGiveawayMsgInfo, giveaway.quantity, LocaleController.formatPluralString("BoldMonths", giveaway.months)));
-        topStringBuilder.append(subTitle);
+        SpannableStringBuilder subTitleBuilder = new SpannableStringBuilder();
+        subTitleBuilder.append(replaceTags(formatPluralStringComma("BoostingGiveawayMsgInfoPlural1", giveaway.quantity)));
+        subTitleBuilder.append("\n");
+        subTitleBuilder.append(replaceTags(formatPluralString("BoostingGiveawayMsgInfoPlural2", giveaway.quantity, LocaleController.formatPluralString("BoldMonths", giveaway.months))));
+        CharSequence subTitle = subTitleBuilder;
+
+        topStringBuilder.append(subTitleBuilder);
         topStringBuilder.append("\n\n");
 
         topStringBuilder.setSpan(new RelativeSizeSpan(0.5f), topStringBuilder.length() - 1, topStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -243,9 +251,9 @@ public class GiveawayMessageCell {
         topStringBuilder.append("\n");
 
         if (giveaway.only_new_subscribers) {
-            topStringBuilder.append(getString("BoostingGiveawayMsgNewSubs", R.string.BoostingGiveawayMsgNewSubs));
+            topStringBuilder.append(formatPluralString("BoostingGiveawayMsgNewSubsPlural", giveaway.channels.size()));
         } else {
-            topStringBuilder.append(getString("BoostingGiveawayMsgAllSubs", R.string.BoostingGiveawayMsgAllSubs));
+            topStringBuilder.append(formatPluralString("BoostingGiveawayMsgAllSubsPlural", giveaway.channels.size()));
         }
 
         CharSequence dateTitle = replaceTags(getString("BoostingWinnersDate", R.string.BoostingWinnersDate));
@@ -268,6 +276,10 @@ public class GiveawayMessageCell {
             maxRowLength = (int) Math.max(maxRowLength, Math.ceil(bottomLayout.getLineWidth(a)));
         }
 
+        if (maxRowLength < dp(180)) {
+            maxRowLength = dp(180);
+        }
+
         if (giveaway.countries_iso2.size() > 0) {
             List countriesWithFlags = new ArrayList<>();
             for (String iso2 : giveaway.countries_iso2) {
@@ -275,7 +287,7 @@ public class GiveawayMessageCell {
                 String flag = LocaleController.getLanguageFlag(iso2);
                 SpannableStringBuilder builder = new SpannableStringBuilder();
                 if (flag != null) {
-                    builder.append(flag).append(" ");
+                    builder.append(flag).append("\u00A0");
                 }
                 builder.append(countryName);
                 countriesWithFlags.add(builder);
@@ -529,6 +541,28 @@ public class GiveawayMessageCell {
         }
     }
 
+    private void checkArraysLimits(int channelsCount) {
+        if (avatarImageReceivers.length < channelsCount) {
+            int oldLength = avatarImageReceivers.length;
+            avatarImageReceivers = Arrays.copyOf(avatarImageReceivers, channelsCount);
+            avatarDrawables = Arrays.copyOf(avatarDrawables, channelsCount);
+            avatarVisible = Arrays.copyOf(avatarVisible, channelsCount);
+            chatTitles = Arrays.copyOf(chatTitles, channelsCount);
+            chatTitleWidths = Arrays.copyOf(chatTitleWidths, channelsCount);
+            needNewRow = Arrays.copyOf(needNewRow, channelsCount);
+            clickRect = Arrays.copyOf(clickRect, channelsCount);
+
+            for (int i = oldLength - 1; i < channelsCount; i++) {
+                avatarImageReceivers[i] = new ImageReceiver(parentView);
+                avatarImageReceivers[i].setAllowLoadingOnAttachedOnly(true);
+                avatarImageReceivers[i].setRoundRadius(AndroidUtilities.dp(12));
+                avatarDrawables[i] = new AvatarDrawable();
+                avatarDrawables[i].setTextSize(AndroidUtilities.dp(18));
+                clickRect[i] = new Rect();
+            }
+        }
+    }
+
     private void setGiftImage(MessageObject messageObject) {
         TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media;
         TLRPC.TL_messages_stickerSet set;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorCountryCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorCountryCell.java
index 6ac63b97b..22dc8de9e 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorCountryCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorCountryCell.java
@@ -67,25 +67,14 @@ public class SelectorCountryCell extends BaseCell {
     private CharSequence getCountryNameWithFlag(TLRPC.TL_help_country country) {
         SpannableStringBuilder sb = new SpannableStringBuilder();
         String flag = LocaleController.getLanguageFlag(country.iso2);
-        if (!LocaleController.isRTL) {
-            if (flag != null) {
-                sb.append(flag).append(" ");
-                sb.setSpan(new SpaceDrawable(16), flag.length(), flag.length() + 1, 0);
-            } else {
-                sb.append(" ");
-                sb.setSpan(new SpaceDrawable(34), 0, 1, 0);
-            }
-            sb.append(country.default_name);
+        if (flag != null) {
+            sb.append(flag).append(" ");
+            sb.setSpan(new SpaceDrawable(16), flag.length(), flag.length() + 1, 0);
         } else {
-            sb.append(country.default_name);
-            if (flag != null) {
-                sb.append(" ").append(flag);
-                sb.setSpan(new SpaceDrawable(16), country.default_name.length(), country.default_name.length() + 1, 0);
-            } else {
-                sb.append(" ");
-                sb.setSpan(new SpaceDrawable(34), country.default_name.length(), country.default_name.length() + 1, 0);
-            }
+            sb.append(" ");
+            sb.setSpan(new SpaceDrawable(34), 0, 1, 0);
         }
+        sb.append(country.default_name);
         return sb;
     }
 
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/GiftedUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/GiftedUserCell.java
index 3900cab7a..57e6d80cd 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/GiftedUserCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/GiftedUserCell.java
@@ -105,8 +105,8 @@ public class GiftedUserCell extends UserCell {
                 avatarImageView.setForUserOrChat(null, avatarDrawable);
                 nameTextView.setRightDrawable(null);
             }
-            String date = LocaleController.getInstance().formatterScheduleDay.format(new Date(boost.date * 1000L));
-            String time = LocaleController.getInstance().formatterDay.format(new Date(boost.date * 1000L));
+            String date = LocaleController.getInstance().formatterScheduleDay.format(new Date(boost.expires * 1000L));
+            String time = LocaleController.getInstance().formatterDay.format(new Date(boost.expires * 1000L));
 
             statusTextView.setText(LocaleController.formatString("BoostingShortMonths", R.string.BoostingShortMonths, months) + " • " + LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, date, time));
 
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/QuoteHighlight.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/QuoteHighlight.java
index 47ab9a8a8..32eed9421 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/QuoteHighlight.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/QuoteHighlight.java
@@ -76,6 +76,9 @@ public class QuoteHighlight extends Path {
             final int blockEnd = Math.min(end - block.charactersOffset, block.charactersEnd - block.charactersOffset);
 
             currentOffsetX = -offsetX;
+            if (block.code && !block.quote) {
+                currentOffsetX += dp(10);
+            }
             currentOffsetY = block.textYOffset + block.padTop;
             minX = block.quote ? dp(10) : 0;
 
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java
index 8a2ea05dc..e9095d531 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java
@@ -45,6 +45,7 @@ public class ReplyMessageLine {
     private float lastHeight;
     private Path color2Path = new Path();
     private Path color3Path = new Path();
+    private int switchedCount = 0;
 
     private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable emoji;
 
@@ -58,6 +59,7 @@ public class ReplyMessageLine {
     public final AnimatedFloat color3Alpha;
     public final AnimatedFloat emojiLoadedT;
     public final AnimatedFloat loadingStateT;
+    public final AnimatedFloat switchStateT;
 
     public ReplyMessageLine(View view) {
         this.parentView = view;
@@ -85,6 +87,7 @@ public class ReplyMessageLine {
         color3Alpha = new AnimatedFloat(view, 0, 400, CubicBezierInterpolator.EASE_OUT_QUINT);
         emojiLoadedT = new AnimatedFloat(view, 0, 440, CubicBezierInterpolator.EASE_OUT_QUINT);
         loadingStateT = new AnimatedFloat(view, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT);
+        switchStateT = new AnimatedFloat(view, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT);
     }
 
     public int getColor() {
@@ -95,7 +98,21 @@ public class ReplyMessageLine {
         return backgroundColor;
     }
 
+    public void setBackgroundColor(int backgroundColor) {
+        this.backgroundColor = backgroundColor;
+    }
+
+    private int wasMessageId;
+    private int wasColorId;
     private void resolveColor(MessageObject messageObject, int colorId, Theme.ResourcesProvider resourcesProvider) {
+        if (wasColorId != colorId) {
+            final int msgId = messageObject != null ? messageObject.getId() : 0;
+            if (msgId == wasMessageId) {
+                switchedCount++;
+            }
+            wasColorId = colorId;
+            wasMessageId = msgId;
+        }
         if (colorId < 7) {
             color1 = color2 = color3 = Theme.getColor(Theme.keys_avatar_nameInMessage[colorId], resourcesProvider);
             hasColor2 = hasColor3 = false;
@@ -351,8 +368,6 @@ public class ReplyMessageLine {
             canvas.drawPaint(color1Paint);
             color1Paint.setAlpha(wasAlpha);
 
-            canvas.clipPath(lineClipPath);
-
             incrementLoadingT();
 
             float x = (float) Math.pow(loadingT / 240f / 4f, .85f) * 4f;
@@ -372,7 +387,6 @@ public class ReplyMessageLine {
 
             parentView.invalidate();
         }
-
         canvas.drawPaint(color1Paint);
         final float color2Alpha = this.color2Alpha.set(hasColor2);
         if (color2Alpha > 0) {
@@ -387,7 +401,8 @@ public class ReplyMessageLine {
             } else {
                 fh = rect.height() - Math.floorMod((int) rect.height(), dp(6.33f + 3 + 3.33f));
             }
-            canvas.translate(0, -((loadingTranslationT + (reversedOut ? 100 : 0)) / 1000f * dp(30) % fh));
+
+            canvas.translate(0, -((loadingTranslationT + switchStateT.set(switchedCount * 425) + (reversedOut ? 100 : 0)) / 1000f * dp(30) % fh));
 
             checkColorPathes(rect.height() * 2);
             int wasAlpha = color2Paint.getAlpha();
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java
index c3f527514..9161dba4f 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java
@@ -42,6 +42,10 @@ public class Text {
         left = layout.getLineCount() > 0 ? layout.getLineLeft(0) : 0;
     }
 
+    public float getTextSize() {
+        return paint.getTextSize();
+    }
+
     public boolean isEmpty() {
         return layout == null || TextUtils.isEmpty(layout.getText());
     }
@@ -121,6 +125,10 @@ public class Text {
         return ellipsizeWidth >= 0 ? Math.min(ellipsizeWidth, width) : width;
     }
 
+    public float getCurrentWidth() {
+        return width;
+    }
+
     @NonNull
     public CharSequence getText() {
         if (layout == null || layout.getText() == null) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert2.java
index 8e97508c1..57b592b66 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert2.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert2.java
@@ -337,10 +337,13 @@ public class TranslateAlert2 extends BottomSheet implements NotificationCenter.N
                     newEntity.length = entity.length;
                     received.entities.set(i, newEntity);
                 }
+            } else if (entity instanceof TLRPC.TL_messageEntityPre) {
+                if (source != null && source.entities != null && i < source.entities.size() && source.entities.get(i) instanceof TLRPC.TL_messageEntityPre) {
+                    entity.language = source.entities.get(i).language;
+                }
             }
         }
         if (source != null && source.text != null && !source.entities.isEmpty()) {
-
             HashMap> srcIndexes = groupEmojiRanges(source.text);
             HashMap> destIndexes = groupEmojiRanges(received.text);
 
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java
index abc67deeb..b0130948d 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java
@@ -1373,13 +1373,13 @@ public class UndoView extends FrameLayout {
                     infoTextView.setText(LocaleController.getString("BoostingSelectUpToWarningUsers", R.string.BoostingSelectUpToWarningUsers));
                     break;
                 case ACTION_BOOSTING_SELECTOR_WARNING_CHANNEL:
-                    infoTextView.setText(LocaleController.formatString("BoostingSelectUpToWarningChannels", R.string.BoostingSelectUpToWarningChannels, BoostRepository.giveawayAddPeersMax()));
+                    infoTextView.setText(LocaleController.formatPluralString("BoostingSelectUpToWarningChannelsPlural", (int) BoostRepository.giveawayAddPeersMax()));
                     break;
                 case ACTION_BOOSTING_SELECTOR_WARNING_COUNTRY:
-                    infoTextView.setText(LocaleController.formatString("BoostingSelectUpToWarningCountries", R.string.BoostingSelectUpToWarningCountries, BoostRepository.giveawayCountriesMax()));
+                    infoTextView.setText(LocaleController.formatPluralString("BoostingSelectUpToWarningCountriesPlural", (int) BoostRepository.giveawayCountriesMax()));
                     break;
                 case ACTION_BOOSTING_AWAIT:
-                    infoTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingWaitWarning", R.string.BoostingWaitWarning, BoostRepository.boostsPerSentGift())));
+                    infoTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatPluralString("BoostingWaitWarningPlural", BoostRepository.boostsPerSentGift())));
                     break;
             }
             layoutParams.leftMargin = AndroidUtilities.dp(58);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java
index fe9d79841..fe24f9893 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java
@@ -110,16 +110,20 @@ public class ViewPagerFixed extends FrameLayout {
     public float getPositionAnimated() {
         float position = 0;
         if (viewPages[0] != null && viewPages[0].getVisibility() == View.VISIBLE) {
-            final float t = Utilities.clamp(1f - Math.abs(viewPages[0].getTranslationX() / (float) AndroidUtilities.displaySize.x), 1, 0);
+            final float t = Utilities.clamp(1f - Math.abs(viewPages[0].getTranslationX() / getAvailableTranslationX()), 1, 0);
             position += currentPosition * t;
         }
         if (viewPages[1] != null && viewPages[1].getVisibility() == View.VISIBLE) {
-            final float t = Utilities.clamp(1f - Math.abs(viewPages[1].getTranslationX() / (float) AndroidUtilities.displaySize.x), 1, 0);
+            final float t = Utilities.clamp(1f - Math.abs(viewPages[1].getTranslationX() / getAvailableTranslationX()), 1, 0);
             position += nextPosition * t;
         }
         return position;
     }
 
+    protected float getAvailableTranslationX() {
+        return (float) AndroidUtilities.displaySize.x;
+    }
+
     protected boolean canScroll(MotionEvent e) {
         return true;
     }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java
index 36bf407a9..d04e9f198 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect.java
@@ -768,7 +768,7 @@ public class SpoilerEffect extends Drawable {
                 layout = StaticLayout.Builder.obtain(sb, 0, sb.length(), textLayout.getPaint(), textLayout.getWidth())
                         .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY)
                         .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE)
-                        .setAlignment(Layout.Alignment.ALIGN_NORMAL)
+                        .setAlignment(textLayout.getAlignment())
                         .setLineSpacing(textLayout.getSpacingAdd(), textLayout.getSpacingMultiplier())
                         .build();
             } else {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java
index 286fb27e6..9ace7cc3c 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java
@@ -5589,7 +5589,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
                         notificationsLocker.unlock();
                         authHintCellAnimating = false;
                         authHintCellProgress = visible ? 1f : 0;
-                        fragmentView.requestLayout();
+                        if (fragmentView != null) {
+                            fragmentView.requestLayout();
+                        }
                         viewPages[0].listView.requestLayout();
                         viewPages[0].listView.setTranslationY(0);
                         if (!visible) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java
index 184e2fc50..e49cbbe63 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java
@@ -6359,8 +6359,12 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
             }
             actionBarLayout.animateThemedValues(theme, accentId, nightTheme, instant, calcInBackgroundEnd);
             if (AndroidUtilities.isTablet()) {
-                layersActionBarLayout.animateThemedValues(theme, accentId, nightTheme, instant);
-                rightActionBarLayout.animateThemedValues(theme, accentId, nightTheme, instant);
+                if (layersActionBarLayout != null) {
+                    layersActionBarLayout.animateThemedValues(theme, accentId, nightTheme, instant);
+                }
+                if (rightActionBarLayout != null) {
+                    rightActionBarLayout.animateThemedValues(theme, accentId, nightTheme, instant);
+                }
             }
         } else if (id == NotificationCenter.notificationsCountUpdated) {
             if (sideMenu != null) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java
index 5181a61ad..124464bdd 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java
@@ -244,7 +244,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
     private PaymentInfoCell paymentInfoCell;
     private TextDetailSettingsCell[] detailSettingsCell = new TextDetailSettingsCell[7];
 
-    private boolean isAcceptTermsChecked;
+    private float shiftDp = -4.5f;
 
     private TLRPC.account_Password currentPassword;
     private boolean waitingForEmail;
@@ -1743,7 +1743,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
                 inputFields[a].setImeOptions(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
                 switch (a) {
                     case FIELD_SAVEDCARD:
-                        inputFields[a].setText(savedCredentialsCard.title);
+                        inputFields[a].setText(savedCredentialsCard == null ? "" : savedCredentialsCard.title);
                         break;
                     case FIELD_SAVEDPASSWORD:
                         inputFields[a].setHint(LocaleController.getString("LoginPassword", R.string.LoginPassword));
@@ -2246,7 +2246,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
             }
 
             if (currentStep == STEP_CHECKOUT) {
-                recurrentAccepted = isAcceptTermsChecked = !isCheckoutPreview;
+                recurrentAccepted = !isCheckoutPreview;
                 bottomLayout = new BottomFrameLayout(context, paymentForm);
                 if (Build.VERSION.SDK_INT >= 21) {
                     View selectorView = new View(context);
@@ -2255,8 +2255,10 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
                 }
                 frameLayout.addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM));
                 bottomLayout.setOnClickListener(v -> {
-                    if (paymentForm.invoice.recurring && !recurrentAccepted) {
-                        AndroidUtilities.shakeViewSpring(recurrentAcceptCell.getTextView(), 4.5f);
+                    if (recurrentAcceptCell != null && !recurrentAccepted) {
+                        shiftDp = -shiftDp;
+                        AndroidUtilities.shakeViewSpring(recurrentAcceptCell.getTextView(), shiftDp);
+                        AndroidUtilities.shakeViewSpring(recurrentAcceptCell.getCheckBox(), shiftDp);
                         try {
                             recurrentAcceptCell.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
                         } catch (Exception ignored) {}
@@ -2340,8 +2342,8 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
                 progressViewButton.setColors(color & 0x2fffffff, color);
                 bottomLayout.addView(progressViewButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
 
-                bottomLayout.setChecked(!paymentForm.invoice.recurring || isAcceptTermsChecked);
-                payTextView.setAlpha(paymentForm.invoice.recurring && !isAcceptTermsChecked ? 0.8f : 1f);
+                bottomLayout.setChecked(recurrentAccepted, false);
+                payTextView.setAlpha(!recurrentAccepted ? 0.8f : 1f);
 
                 doneItem.setEnabled(false);
                 doneItem.getContentView().setVisibility(View.INVISIBLE);
@@ -2407,9 +2409,10 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
                     }
                 });
 
+                recurrentAcceptCell = null;
                 if (paymentForm.invoice.terms_url != null) {
                     recurrentAcceptCell = new RecurrentPaymentsAcceptCell(context, getResourceProvider());
-                    recurrentAcceptCell.setChecked(paymentForm.invoice.recurring && isAcceptTermsChecked);
+                    recurrentAcceptCell.setChecked(recurrentAccepted);
                     String str = LocaleController.getString(R.string.PaymentCheckoutAcceptRecurrent);
                     SpannableStringBuilder sb = new SpannableStringBuilder(str);
                     int firstIndex = str.indexOf('*'), lastIndex = str.lastIndexOf('*');
@@ -2437,7 +2440,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
                         recurrentAccepted = !recurrentAccepted;
                         recurrentAcceptCell.setChecked(recurrentAccepted);
 
-                        bottomLayout.setChecked(recurrentAccepted);
+                        bottomLayout.setChecked(recurrentAccepted, true);
                     });
                     frameLayout.addView(recurrentAcceptCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 0, 0, 0, 48));
                 }
@@ -4497,8 +4500,6 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
 
         public BottomFrameLayout(@NonNull Context context, TLRPC.TL_payments_paymentForm paymentForm) {
             super(context);
-
-            progress = paymentForm.invoice.recurring && !isAcceptTermsChecked ? 0f : 1f;
             setWillNotDraw(false);
         }
 
@@ -4511,31 +4512,39 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
             canvas.drawCircle(LocaleController.isRTL ? getWidth() - AndroidUtilities.dp(28) : AndroidUtilities.dp(28), -AndroidUtilities.dp(28), Math.max(getWidth(), getHeight()) * progress, paint);
         }
 
-        public void setChecked(boolean checked) {
+        public void setChecked(boolean checked, boolean animated) {
             if (springAnimation != null) {
                 springAnimation.cancel();
             }
             float to = checked ? 1f : 0f;
-            if (progress == to) {
-                return;
-            }
-            springAnimation = new SpringAnimation(new FloatValueHolder(progress * 100f))
-                    .setSpring(new SpringForce(to * 100f)
-                            .setStiffness(checked ? 500f : 650f)
-                            .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY));
-            springAnimation.addUpdateListener((animation, value, velocity) -> {
-                progress = value / 100f;
+            if (animated) {
+                if (progress == to) {
+                    return;
+                }
+                springAnimation = new SpringAnimation(new FloatValueHolder(progress * 100f))
+                        .setSpring(new SpringForce(to * 100f)
+                                .setStiffness(checked ? 500f : 650f)
+                                .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY));
+                springAnimation.addUpdateListener((animation, value, velocity) -> {
+                    progress = value / 100f;
+                    if (payTextView != null) {
+                        payTextView.setAlpha(0.8f + 0.2f * progress);
+                    }
+                    invalidate();
+                });
+                springAnimation.addEndListener((animation, canceled1, value, velocity) -> {
+                    if (animation == springAnimation) {
+                        springAnimation = null;
+                    }
+                });
+                springAnimation.start();
+            } else {
+                progress = to;
                 if (payTextView != null) {
                     payTextView.setAlpha(0.8f + 0.2f * progress);
                 }
                 invalidate();
-            });
-            springAnimation.addEndListener((animation, canceled1, value, velocity) -> {
-                if (animation == springAnimation) {
-                    springAnimation = null;
-                }
-            });
-            springAnimation.start();
+            }
         }
     }
 }
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java
index 1c084e107..da47eec0b 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java
@@ -3,6 +3,7 @@ package org.telegram.ui;
 import static android.content.DialogInterface.BUTTON_NEGATIVE;
 import static org.telegram.messenger.AndroidUtilities.dp;
 import static org.telegram.messenger.AndroidUtilities.dpf2;
+import static org.telegram.messenger.AndroidUtilities.getPath;
 import static org.telegram.ui.Components.Premium.LimitReachedBottomSheet.TYPE_BOOSTS_FOR_COLOR;
 import static org.telegram.ui.Components.Premium.LimitReachedBottomSheet.TYPE_BOOSTS_FOR_USERS;
 
@@ -16,7 +17,9 @@ import android.graphics.Path;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
+import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
+import android.icu.util.Measure;
 import android.os.Build;
 import android.os.Bundle;
 import android.text.SpannableStringBuilder;
@@ -47,6 +50,7 @@ import org.telegram.messenger.MessagesController;
 import org.telegram.messenger.NotificationCenter;
 import org.telegram.messenger.R;
 import org.telegram.messenger.UserConfig;
+import org.telegram.messenger.Utilities;
 import org.telegram.tgnet.TLRPC;
 import org.telegram.ui.ActionBar.ActionBar;
 import org.telegram.ui.ActionBar.AlertDialog;
@@ -84,7 +88,7 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
     private RecyclerView.Adapter listAdapter;
     private FrameLayout buttonContainer;
     private ButtonWithCounterView button;
-    private PeerColorPicker peerColorPicker;
+    private PeerColorGrid peerColorPicker;
 
     private int selectedColor;
     private long selectedEmoji;
@@ -98,6 +102,7 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
     int infoRow;
     int iconRow;
     int info2Row;
+    int buttonRow;
 
     int rowCount;
 
@@ -105,6 +110,7 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
     private static final int VIEW_TYPE_COLOR_PICKER = 1;
     private static final int VIEW_TYPE_INFO = 2;
     private static final int VIEW_TYPE_ICON = 3;
+    private static final int VIEW_TYPE_BUTTONPAD = 5;
 
     public PeerColorActivity(long dialogId) {
         super();
@@ -183,13 +189,25 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
 
         FrameLayout frameLayout = new FrameLayout(context);
 
-        listView = new RecyclerListView(context);
-        ((DefaultItemAnimator)listView.getItemAnimator()).setSupportsChangeAnimations(false);
+        listView = new RecyclerListView(context) {
+            @Override
+            protected void onMeasure(int widthSpec, int heightSpec) {
+                super.onMeasure(widthSpec, heightSpec);
+                updateButtonY();
+            }
+
+            @Override
+            protected void onLayout(boolean changed, int l, int t, int r, int b) {
+                super.onLayout(changed, l, t, r, b);
+                updateButtonY();
+            }
+        };
+        ((DefaultItemAnimator) listView.getItemAnimator()).setSupportsChangeAnimations(false);
         listView.setLayoutManager(new LinearLayoutManager(context));
         listView.setAdapter(listAdapter = new RecyclerListView.SelectionAdapter() {
             @Override
             public boolean isEnabled(RecyclerView.ViewHolder holder) {
-                return holder.getItemViewType() == VIEW_TYPE_COLOR_PICKER || holder.getItemViewType() == VIEW_TYPE_ICON;
+                return holder.getItemViewType() == VIEW_TYPE_ICON;
             }
 
             @NonNull
@@ -211,18 +229,12 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
                         view = cell;
                         break;
                     case VIEW_TYPE_COLOR_PICKER:
-                        PeerColorPicker colorPicker = peerColorPicker = new PeerColorPicker(context, currentAccount, getResourceProvider());
-                        colorPicker.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, getResourceProvider()));
+                        PeerColorGrid colorPicker = peerColorPicker = new PeerColorGrid(context, currentAccount);
+                        colorPicker.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite));
                         colorPicker.setSelected(selectedColor);
-                        colorPicker.layoutManager.scrollToPositionWithOffset(colorPicker.selectedPosition, AndroidUtilities.displaySize.x / 2);
-                        colorPicker.setOnItemClickListener((item, position) -> {
-                            selectedColor = colorPicker.toColorId(position);
-                            colorPicker.setSelectedPosition(position);
-                            if (item.getLeft() - colorPicker.getPaddingLeft() < AndroidUtilities.dp(24)) {
-                                colorPicker.smoothScrollBy(position == 0 ? Math.max(-(item.getLeft() - colorPicker.getPaddingLeft()), -AndroidUtilities.dp(64)) : -AndroidUtilities.dp(64), 0);
-                            } else if (item.getRight() - colorPicker.getPaddingLeft() > AndroidUtilities.displaySize.x - colorPicker.getPaddingLeft() - colorPicker.getPaddingRight() - AndroidUtilities.dp(24)) {
-                                colorPicker.smoothScrollBy(position == colorPicker.adapter.getItemCount() - 1 ? Math.min(AndroidUtilities.displaySize.x - item.getRight() - colorPicker.getPaddingRight(), AndroidUtilities.dp(64)) : AndroidUtilities.dp(64), 0);
-                            }
+                        colorPicker.setOnColorClick(colorId -> {
+                            selectedColor = colorId;
+                            colorPicker.setSelected(colorId);
                             updateMessages();
                             if (setReplyIconCell != null) {
                                 setReplyIconCell.invalidate();
@@ -230,6 +242,14 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
                         });
                         view = colorPicker;
                         break;
+                    case VIEW_TYPE_BUTTONPAD:
+                        view = new View(context) {
+                            @Override
+                            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+                                super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(dp(14 + 48 + 14), MeasureSpec.EXACTLY));
+                            }
+                        };
+                        break;
                     case VIEW_TYPE_ICON:
                         SetReplyIconCell setcell = setReplyIconCell = new SetReplyIconCell(context);
                         setcell.update(false);
@@ -285,6 +305,9 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
                 if (position == iconRow) {
                     return VIEW_TYPE_ICON;
                 }
+                if (position == buttonRow) {
+                    return VIEW_TYPE_BUTTONPAD;
+                }
                 if (position == getItemCount() - 1) {
                     return 4;
                 }
@@ -314,6 +337,12 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
         buttonContainer.addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48));
 
         frameLayout.addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM));
+        listView.setOnScrollListener(new RecyclerView.OnScrollListener() {
+            @Override
+            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+                updateButtonY();
+            }
+        });
 
         fragmentView = contentView = frameLayout;
 
@@ -323,6 +352,29 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
         return contentView;
     }
 
+    private void updateButtonY() {
+        if (buttonContainer == null) {
+            return;
+        }
+        final int lastPosition = listAdapter.getItemCount() - 1;
+        boolean foundLastPosition = false;
+        int maxTop = 0;
+        for (int i = 0; i < listView.getChildCount(); ++i) {
+            View child = listView.getChildAt(i);
+            final int position = listView.getChildAdapterPosition(child);
+            if (position != RecyclerListView.NO_POSITION && position <= lastPosition) {
+                maxTop = Math.max(maxTop, child.getTop());
+                if (position == lastPosition) {
+                    foundLastPosition = true;
+                }
+            }
+        }
+        if (!foundLastPosition) {
+            maxTop = listView.getMeasuredHeight();
+        }
+        buttonContainer.setTranslationY(Math.max(0, maxTop - (listView.getMeasuredHeight() - dp(14 + 48 + 14))));
+    }
+
     private void showBoostLimit(boolean error) {
         getMessagesController().getBoostsController().getBoostsStats(dialogId, boostsStatus -> {
             if (error || boostsStatus.level < getMessagesController().channelColorLevelMin) {
@@ -688,9 +740,9 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
         rowCount = 0;
         previewRow = rowCount++;
         colorPickerRow = rowCount++;
-        infoRow = rowCount++;
         iconRow = rowCount++;
-        info2Row = rowCount++;
+        infoRow = rowCount++;
+        buttonRow = rowCount++;
     }
 
     @Override
@@ -1136,6 +1188,276 @@ public class PeerColorActivity extends BaseFragment implements NotificationCente
         }
     }
 
+    public static class PeerColorGrid extends View {
+
+        public class ColorButton {
+            private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            private final Paint paint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
+            private final Paint paint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
+            private final Paint paint3 = new Paint(Paint.ANTI_ALIAS_FLAG);
+            private final Path circlePath = new Path();
+            private final Path color2Path = new Path();
+            private boolean hasColor2, hasColor3;
+
+            private final ButtonBounce bounce = new ButtonBounce(PeerColorGrid.this);
+
+            public ColorButton() {
+                backgroundPaint.setStyle(Paint.Style.STROKE);
+            }
+
+            public void setBackgroundColor(int backgroundColor) {
+                backgroundPaint.setColor(backgroundColor);
+            }
+
+            public void set(int color) {
+                hasColor2 = hasColor3 = false;
+                paint1.setColor(color);
+            }
+
+            public void set(int color1, int color2) {
+                hasColor2 = true;
+                hasColor3 = false;
+                paint1.setColor(color1);
+                paint2.setColor(color2);
+            }
+
+            public void set(MessagesController.PeerColor color) {
+                if (color == null) {
+                    return;
+                }
+                if (Theme.isCurrentThemeDark() && color.hasColor2() && !color.hasColor3()) {
+                    paint1.setColor(color.getColor2());
+                    paint2.setColor(color.getColor1());
+                } else {
+                    paint1.setColor(color.getColor1());
+                    paint2.setColor(color.getColor2());
+                }
+                paint3.setColor(color.getColor3());
+                hasColor2 = color.hasColor2();
+                hasColor3 = color.hasColor3();
+            }
+
+            private boolean selected;
+            private final AnimatedFloat selectedT = new AnimatedFloat(PeerColorGrid.this, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT);
+            public void setSelected(boolean selected, boolean animated) {
+                this.selected = selected;
+                if (!animated) {
+                    selectedT.set(selected, true);
+                }
+                invalidate();
+            }
+
+            private static final int VIEW_SIZE_DP = 56;
+            private static final int CIRCLE_RADIUS_DP = 20;
+
+            public int id;
+            private final RectF bounds = new RectF();
+            public final RectF clickBounds = new RectF();
+            public void layout(int id, RectF bounds) {
+                this.id = id;
+                this.bounds.set(bounds);
+            }
+            public void layoutClickBounds(RectF bounds) {
+                this.clickBounds.set(bounds);
+            }
+
+            protected void draw(Canvas canvas) {
+                canvas.save();
+                final float s = bounce.getScale(.05f);
+                canvas.scale(s, s, bounds.centerX(), bounds.centerY());
+
+                canvas.save();
+                circlePath.rewind();
+                circlePath.addCircle(bounds.centerX(), bounds.centerY(), Math.min(bounds.height() / 2f, bounds.width() / 2f), Path.Direction.CW);
+                canvas.clipPath(circlePath);
+                canvas.drawPaint(paint1);
+                if (hasColor2) {
+                    color2Path.rewind();
+                    color2Path.moveTo(bounds.right, bounds.top);
+                    color2Path.lineTo(bounds.right, bounds.bottom);
+                    color2Path.lineTo(bounds.left, bounds.bottom);
+                    color2Path.close();
+                    canvas.drawPath(color2Path, paint2);
+                }
+                canvas.restore();
+
+                if (hasColor3) {
+                    canvas.save();
+                    final float color3Size = (bounds.width() * .315f);
+                    AndroidUtilities.rectTmp.set(
+                        bounds.centerX() - color3Size / 2f,
+                        bounds.centerY() - color3Size / 2f,
+                        bounds.centerX() + color3Size / 2f,
+                        bounds.centerY() + color3Size / 2f
+                    );
+                    canvas.rotate(45f, bounds.centerX(), bounds.centerY());
+                    canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(2.33f), dp(2.33f), paint3);
+                    canvas.restore();
+                }
+
+                final float selectT = selectedT.set(selected);
+
+                if (selectT > 0) {
+                    backgroundPaint.setStrokeWidth(dpf2(2));
+                    canvas.drawCircle(
+                        bounds.centerX(), bounds.centerY(),
+                        Math.min(bounds.height() / 2f, bounds.width() / 2f) + backgroundPaint.getStrokeWidth() * AndroidUtilities.lerp(.5f, -2f, selectT),
+                        backgroundPaint
+                    );
+                }
+
+                canvas.restore();
+            }
+
+            private boolean pressed;
+            public boolean isPressed() {
+                return pressed;
+            }
+
+            public void setPressed(boolean pressed) {
+                bounce.setPressed(this.pressed = pressed);
+            }
+        }
+
+        private int currentAccount;
+
+        private ColorButton[] buttons;
+
+        public PeerColorGrid(Context context, int currentAccount) {
+            super(context);
+            this.currentAccount = currentAccount;
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            final int width = MeasureSpec.getSize(widthMeasureSpec);
+
+            final MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors;
+            final int colorsCount = 7 + (peerColors == null ? 0 : peerColors.colors.size());
+            final int columns = 7;
+
+            final float iconSize = Math.min(dp(38 + 16), width / (columns + (columns + 1) * .28947f));
+            final float horizontalSeparator = iconSize * .28947f;
+            final float verticalSeparator = iconSize * .315789474f;
+
+            final int rows = colorsCount / columns;
+            final int height = (int) (iconSize * rows + verticalSeparator * (rows + 1));
+
+            setMeasuredDimension(width, height);
+
+            if (buttons == null || buttons.length != colorsCount) {
+                buttons = new ColorButton[colorsCount];
+                for (int i = 0; i < colorsCount; ++i) {
+                    buttons[i] = new ColorButton();
+                    buttons[i].setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
+                    if (i < 7) {
+                        buttons[i].set(Theme.getColor(Theme.keys_avatar_nameInMessage[i]));
+                    } else if (peerColors != null) {
+                        buttons[i].set(peerColors.getColor(i));
+                    }
+                }
+            }
+            final float itemsWidth = iconSize * columns + horizontalSeparator * (columns + 1);
+            final float startX = (width - itemsWidth) / 2f + horizontalSeparator;
+            if (buttons != null) {
+                float x = startX, y = verticalSeparator;
+                for (int i = 0; i < buttons.length; ++i) {
+                    AndroidUtilities.rectTmp.set(x, y, x + iconSize, y + iconSize);
+                    buttons[i].layout(i, AndroidUtilities.rectTmp);
+                    AndroidUtilities.rectTmp.inset(-horizontalSeparator / 2, -verticalSeparator / 2);
+                    buttons[i].layoutClickBounds(AndroidUtilities.rectTmp);
+                    buttons[i].setSelected(i == selectedColorId, false);
+
+                    if (i % columns == (columns - 1)) {
+                        x = startX;
+                        y += iconSize + verticalSeparator;
+                    } else {
+                        x += iconSize + horizontalSeparator;
+                    }
+                }
+            }
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+            if (buttons != null) {
+                for (int i = 0; i < buttons.length; ++i) {
+                    buttons[i].draw(canvas);
+                }
+            }
+            canvas.drawRect(dp(21), getMeasuredHeight() - 1, getMeasuredWidth() - dp(21), getMeasuredHeight(), Theme.dividerPaint);
+        }
+
+        private int selectedColorId = 0;
+        public void setSelected(int colorId) {
+            selectedColorId = colorId;
+            if (buttons != null) {
+                for (int i = 0; i < buttons.length; ++i) {
+                    buttons[i].setSelected(i == colorId, true);
+                }
+            }
+        }
+        public int getColorId() {
+            return selectedColorId;
+        }
+
+        private Utilities.Callback onColorClick;
+        public void setOnColorClick(Utilities.Callback onColorClick) {
+            this.onColorClick = onColorClick;
+        }
+
+        private ColorButton pressedButton;
+        @Override
+        public boolean dispatchTouchEvent(MotionEvent event) {
+            ColorButton button = null;
+            if (buttons != null) {
+                for (int i = 0; i < buttons.length; ++i) {
+                    if (buttons[i].clickBounds.contains(event.getX(), event.getY())) {
+                        button = buttons[i];
+                        break;
+                    }
+                }
+            }
+            if (event.getAction() == MotionEvent.ACTION_DOWN) {
+                pressedButton = button;
+                if (button != null) {
+                    button.setPressed(true);
+                }
+                if (getParent() != null) {
+                    getParent().requestDisallowInterceptTouchEvent(true);
+                }
+            } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
+                if (pressedButton != button) {
+                    if (pressedButton != null) {
+                        pressedButton.setPressed(false);
+                    }
+                    if (button != null) {
+                        button.setPressed(true);
+                    }
+                    if (pressedButton != null && button != null) {
+                        if (onColorClick != null) {
+                            onColorClick.run(button.id);
+                        }
+                    }
+                    pressedButton = button;
+                }
+            } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
+                if (event.getAction() == MotionEvent.ACTION_UP && pressedButton != null) {
+                    if (onColorClick != null) {
+                        onColorClick.run(pressedButton.id);
+                    }
+                }
+                if (buttons != null) {
+                    for (int i = 0; i < buttons.length; ++i) {
+                        buttons[i].setPressed(false);
+                    }
+                }
+                pressedButton = null;
+            }
+            return true;
+        }
+    }
+
     public static class PeerColorDrawable extends Drawable {
 
         public static PeerColorDrawable from(int currentAccount, int colorId) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java
index b9e4c13dd..0b68e7e51 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java
@@ -7672,7 +7672,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
         }
 
         if (usedSurfaceView) {
-            videoPlayer.player.setVideoTextureView(null);
+            if (videoPlayer.player != null) {
+                videoPlayer.player.setVideoTextureView(null);
+            }
             videoPlayer.setSurfaceView(videoSurfaceView);
             videoSurfaceView.setVisibility(View.INVISIBLE);
             waitingForFirstTextureUpload = 2;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java
index 0785f826b..50f404e7a 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java
@@ -927,7 +927,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification
             if (isPremium) {
                 resId = isYearTier ? R.string.UpgradePremiumPerYear : R.string.UpgradePremiumPerMonth;
             } else {
-                price = tier.getFormattedPricePerMonthRounded();
+                price = tier.getFormattedPricePerMonth();
                 resId = R.string.SubscribeToPremium;
             }
             return LocaleController.formatString(resId, price);
@@ -1834,14 +1834,6 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification
             return googlePlayProductDetails == null ? "" : BillingController.getInstance().formatCurrency(getPricePerYear(), getCurrency(), 6);
         }
 
-        public String getFormattedPricePerMonthRounded() {
-            if (BuildVars.useInvoiceBilling() || subscriptionOption.store_product == null) {
-                return BillingController.getInstance().formatCurrency(getPricePerMonth(), getCurrency(), BillingController.getInstance().getCurrencyExp(getCurrency()), true);
-            }
-
-            return googlePlayProductDetails == null ? "" : BillingController.getInstance().formatCurrency(getPricePerMonth(), getCurrency(), 6, true);
-        }
-
         public String getFormattedPricePerMonth() {
             if (BuildVars.useInvoiceBilling() || subscriptionOption.store_product == null) {
                 return BillingController.getInstance().formatCurrency(getPricePerMonth(), getCurrency());
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java
index 48375ab6b..4e172834a 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java
@@ -1942,8 +1942,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
                     Bundle args = new Bundle();
                     args.putLong("user_id", user.id);
                     args.putBoolean("addContact", true);
-                    presentFragment(new ContactAddActivity(args, resourcesProvider));
-                    wentToAddContacts = true;
+                    openAddToContact(user, args);
                 } else if (id == share_contact) {
                     Bundle args = new Bundle();
                     args.putBoolean("onlySelect", true);
@@ -1957,7 +1956,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
                     Bundle args = new Bundle();
                     args.putLong("user_id", userId);
                     presentFragment(new ContactAddActivity(args, resourcesProvider));
-                    wentToAddContacts = true;
                 } else if (id == delete_contact) {
                     final TLRPC.User user = getMessagesController().getUser(userId);
                     if (user == null || getParentActivity() == null) {
@@ -3163,8 +3161,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
                 args.putString("phone", vcardPhone);
                 args.putString("first_name_card", vcardFirstName);
                 args.putString("last_name_card", vcardLastName);
-                presentFragment(new ContactAddActivity(args, resourcesProvider));
-                wentToAddContacts = true;
+                openAddToContact(user, args);
             } else if (position == reportReactionRow) {
                 AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider);
                 builder.setTitle(LocaleController.getString("ReportReaction", R.string.ReportReaction));
@@ -11155,8 +11152,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
         }
     }
 
-    private boolean wentToAddContacts;
-
     @Override
     public void onBecomeFullyVisible() {
         super.onBecomeFullyVisible();
@@ -11170,11 +11165,48 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
             combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56));
             writeButton.setBackground(combinedDrawable);
         } catch (Exception e) {}
+    }
 
-        if (wentToAddContacts) {
-            updateListAnimated(false);
-            wentToAddContacts = false;
-        }
+    @SuppressLint("NotifyDataSetChanged")
+    private void openAddToContact(TLRPC.User user, Bundle args) {
+        ContactAddActivity contactAddActivity = new ContactAddActivity(args, resourcesProvider);
+        contactAddActivity.setDelegate(() -> {
+            int currentAddToContactsRow = addToContactsRow;
+            if (currentAddToContactsRow >= 0) {
+                if (sharedMediaRow == -1) {
+                    updateRowsIds();
+                    listAdapter.notifyDataSetChanged();
+                } else {
+                    updateListAnimated(false);
+                }
+            }
+
+            if (sharedMediaRow == -1) {
+                if (isInLandscapeMode || AndroidUtilities.isTablet()) {
+                    listView.setPadding(0, AndroidUtilities.dp(88), 0, 0);
+                    expandAnimator.cancel();
+                    expandAnimatorValues[0] = 1f;
+                    expandAnimatorValues[1] = 0f;
+                    setAvatarExpandProgress(1f);
+                    extraHeight = AndroidUtilities.dp(88);
+                } else {
+                    final int actionBarHeight = ActionBar.getCurrentActionBarHeight() + (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0);
+                    int ws = View.MeasureSpec.makeMeasureSpec(listView.getMeasuredWidth(), View.MeasureSpec.EXACTLY);
+                    int hs = View.MeasureSpec.makeMeasureSpec(listView.getMeasuredHeight(), View.MeasureSpec.UNSPECIFIED);
+                    int contentHeight = 0;
+                    for (int i = 0; i < listAdapter.getItemCount(); i++) {
+                        RecyclerView.ViewHolder holder = listAdapter.createViewHolder(null, listAdapter.getItemViewType(i));
+                        listAdapter.onBindViewHolder(holder, i);
+                        holder.itemView.measure(ws, hs);
+                        contentHeight += holder.itemView.getMeasuredHeight();
+                    }
+                    int paddingBottom = Math.max(0, fragmentView.getMeasuredHeight() - (contentHeight + AndroidUtilities.dp(88) + actionBarHeight));
+                    listView.setPadding(0, listView.getPaddingTop(), 0, paddingBottom);
+                }
+            }
+            undoView.showWithAction(dialogId, UndoView.ACTION_CONTACT_ADDED, user);
+        });
+        presentFragment(contactAddActivity);
     }
 
     private boolean isQrNeedVisible() {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java
index 3b5c693f6..47062a736 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java
@@ -694,7 +694,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
         });
 
         avatarContainer.setTitleColors(Theme.getColor(Theme.key_player_actionBarTitle), Theme.getColor(Theme.key_player_actionBarSubtitle));
-        actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false);
+        actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarTitle), false);
         actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), false);
         actionBar.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
 
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java
index 8be3ab118..783d416c6 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java
@@ -2551,6 +2551,17 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
             avatarDrawable.setInfo(chat);
             headerView.backupImageView.getImageReceiver().setForUserOrChat(chat, avatarDrawable);
             headerView.titleView.setText(chat.title);
+
+            if (chat != null && chat.verified) {
+                Drawable verifyDrawable = ContextCompat.getDrawable(getContext(), R.drawable.verified_profile).mutate();
+                verifyDrawable.setAlpha(255);
+                CombinedDrawable drawable = new CombinedDrawable(verifyDrawable, null);
+                drawable.setFullsize(true);
+                drawable.setCustomSize(AndroidUtilities.dp(16), AndroidUtilities.dp(16));
+                headerView.titleView.setRightDrawable(drawable);
+            } else {
+                headerView.titleView.setRightDrawable(null);
+            }
         }
         if (isActive && (isSelf || isChannel)) {
             storiesController.pollViewsForSelfStories(dialogId, true);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TextMessageEnterTransition.java b/TMessagesProj/src/main/java/org/telegram/ui/TextMessageEnterTransition.java
index 7d3f8ea7e..79dbeec3e 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/TextMessageEnterTransition.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/TextMessageEnterTransition.java
@@ -639,7 +639,7 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain
                 replyImageSz = AndroidUtilities.lerp(AndroidUtilities.dp(35), sz, progressX);
                 messageView.replyImageReceiver.setImageCoords(
                     AndroidUtilities.lerp(replyX, replySelectorRect.left + AndroidUtilities.dp(8), progressX),
-                    AndroidUtilities.lerp(replyY, replySelectorRect.top + AndroidUtilities.dp(5), progressX),
+                    AndroidUtilities.lerp(replyY, replySelectorRect.top + AndroidUtilities.dp((messageView.isReplyQuote && messageView.replyTextLayout != null && messageView.replyTextLayout.getLineCount() <= 1 ? 2 : 0) + 5), progressX),
                     replyImageSz, replyImageSz
                 );
                 messageView.replyImageReceiver.draw(canvas);
@@ -690,8 +690,17 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain
 
             if (messageView.replyTextLayout != null) {
                 canvas.save();
-                final float offsetX2 = (messageView.needReplyImage && (!messageView.isReplyQuote || messageView.replyTextRTL) ? replyImageSz + AndroidUtilities.dp(3) : 0) + AndroidUtilities.dp(messageView.isReplyQuote && messageView.needReplyImage ? -2 : 0);
-                canvas.translate(replyMessageX + offsetX2, replyY + AndroidUtilities.lerp(AndroidUtilities.dp(19), Theme.chat_replyNamePaint.getTextSize() + AndroidUtilities.dp(4) + offsetY, progressX));
+                float left = replyToMessageX;
+                if (messageView.isReplyQuote && messageView.needReplyImage) {
+                    left -= AndroidUtilities.dp(2);
+                }
+                if (messageView.needReplyImage && (!messageView.isReplyQuote || messageView.replyTextRTL)) {
+                    left += replyImageSz + AndroidUtilities.dp(3);
+                }
+                if (messageView.replyTextRTL && messageView.replyTextOffset > 0) {
+                    left = replySelectorRect.right - AndroidUtilities.dp(8) - messageView.replyTextLayout.getWidth() - offset * progressX;
+                }
+                canvas.translate(AndroidUtilities.lerp(fromReplayX - messageView.replyTextOffset, left, progressX), replyY + AndroidUtilities.lerp(AndroidUtilities.dp(19), Theme.chat_replyNamePaint.getTextSize() + AndroidUtilities.dp(4) + offsetY, progressX));
 
                 canvas.save();
                 SpoilerEffect.clipOutCanvas(canvas, messageView.replySpoilers);
diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml
index 34eed123c..2ae80b0ce 100644
--- a/TMessagesProj/src/main/res/values/strings.xml
+++ b/TMessagesProj/src/main/res/values/strings.xml
@@ -1266,6 +1266,7 @@
     Delete for %1$s
     Delete for all members
     Text copied to clipboard
+    Code copied to clipboard
     Hold to record audio.
     Hold to record audio. Tap to switch to video.
     Hold to record video. Tap to switch to audio.
@@ -4717,6 +4718,12 @@
     %1$d-months
     %1$d-months
     %1$d-months
+    %1$d-month
+    %1$d-month
+    %1$d-month
+    %1$d-month
+    %1$d-month
+    %1$d-month
     **%1$d** month
     **%1$d** months
     **%1$d** months
@@ -5879,8 +5886,6 @@
     Gift Telegram Premium
     Let **%1$s** enjoy exclusive features of Telegram with **Telegram Premium**.
     Telegram Premium
-    %1$s subscriptions
-    %1$d Telegram Premium
     Go **beyond the limits**, get exclusive features and support us by subscribing to **Telegram Premium**.
     You are all set!
     Thank you for subscribing to **Telegram Premium**.\nHere’s what is now unlocked.
@@ -7165,7 +7170,8 @@
     All viewers
     Reactions First
     Newest First
-    Choose the order for the 
list of viewers.
+    Choose the order for the 
+list of viewers.
     None of your contacts viewed this story.
     Viewers
     You are in Stealth Mode now
@@ -7227,7 +7233,7 @@
     Congratulations!
     You\'ve received a gift\nfrom **%s**.
     You\'ve received a gift.
-    Your gift is a **Telegram Premium**\n subscription for %s.
+    Your gift is a **Telegram Premium**\nsubscription for %s.
     Unclaimed Prize
     You have an unclaimed prize from a giveaway by **%s**.
     This prize is a **Telegram Premium** subscription for %s.
@@ -7236,12 +7242,22 @@
     Open Gift Link
     Save Recipients
     %s just started a giveaway of Telegram Premium subscriptions to its followers.
-    %d boost
-    %d boost
-    %d boosts
-    %d boosts
-    %d boosts
-    %d boosts
+    %d boost
+    %d boost
+    %d boosts
+    %d boosts
+    %d boosts
+    %d boosts
+    %2$s subscription
+    %2$s subscriptions
+    %2$s subscriptions
+    %2$s subscriptions
+    %2$s subscriptions
+    %1$d Telegram Premium
+    %1$d Telegram Premium
+    %1$d Telegram Premium
+    %1$d Telegram Premium
+    %1$d Telegram Premium
     Get Boosts via Gifts
     Use Link
     Share this link with your subsсribers to get more boosts.
@@ -7263,7 +7279,7 @@
     %1$d Gifts
     %1$d Gifts
     %1$d Boosts
-    %1$d Boosts
+    %1$d Boost
     %1$d Boosts
     %1$d Boosts
     %1$d Boosts
@@ -7312,7 +7328,11 @@
     Date
     Prepaid giveaways
     Prepaid giveaway
-    %1$d subscriptions for %2$s
+    %1$d subscription for %2$s
+    %1$d subscriptions for %2$s
+    %1$d subscriptions for %2$s
+    %1$d subscriptions for %2$s
+    %1$d subscriptions for %2$s
     select recipients
     from all countries
     from %1$s
@@ -7325,7 +7345,7 @@
     from %1$d countries
     from %1$d countries
     You can also **send this link** to a friend as a gift.
-    You can also **send this link** to a anyone as a gift.
+    You can also **send this link** to anyone as a gift.
     This link was used on %s.
     Quantity of prizes
     Choose how many Premium subscriptions to give away and boosts to receive.
@@ -7355,21 +7375,41 @@
     On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s**.
     On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s**.
     On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s**.
-    On **%2$s**, Telegram will automatically select **%3$s** random user that joined **%4$s** and **%5$s** other listed channels.
-    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** and **%5$s** other listed channels.
-    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** and **%5$s** other listed channels.
-    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** and **%5$s** other listed channels.
-    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** and **%5$s** other listed channels.
+    On **%2$s**, Telegram will automatically select **%3$s** random user that joined **%4$s** %5$s.
+    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram automatically selected **%3$s** random user that joined **%4$s** %5$s.
+    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** %5$s.
+    and **%1$d** other listed channel
+    and **%1$d** other listed channels
+    and **%1$d** other listed channels
+    and **%1$d** other listed channels
+    and **%1$d** other listed channels
+    On **%2$s**, Telegram will automatically select **%3$s** random user that joined **%4$s** %5$s.
+    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram automatically selected **%3$s** random user that joined **%4$s** %5$s.
+    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** %5$s.
+    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** %5$s.
+    and **%1$d** other listed channel after **%2$s** on **%3$s**
+    and **%1$d** other listed channels after **%2$s** on **%3$s**
+    and **%1$d** other listed channels after **%2$s** on **%3$s**
+    and **%1$d** other listed channels after **%2$s** on **%3$s**
+    and **%1$d** other listed channels after **%2$s** on **%3$s**
     On **%2$s**, Telegram will automatically select **%3$s** random user that joined **%4$s** after **%5$s** on **%6$s**.
     On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** after **%5$s** on **%6$s**.
     On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** after **%5$s** on **%6$s**.
     On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** after **%5$s** on **%6$s**.
     On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** after **%5$s** on **%6$s**.
-    On **%2$s**, Telegram will automatically select **%3$s** random user that joined **%4$s** and **%5$s** other listed channels after **%6$s** on **%7$s**.
-    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** and **%5$s** other listed channels after **%6$s** on **%7$s**.
-    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** and **%5$s** other listed channels after **%6$s** on **%7$s**.
-    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** and **%5$s** other listed channels after **%6$s** on **%7$s**.
-    On **%2$s**, Telegram will automatically select **%3$s** random users that joined **%4$s** and **%5$s** other listed channels after **%6$s** on **%7$s**.
     This giveaway was sponsored by the admins of **%2$s**, who acquired **%3$s Telegram Premium** subscription for %4$s for its followers.
     This giveaway was sponsored by the admins of **%2$s**, who acquired **%3$s Telegram Premium** subscriptions for %4$s for its followers.
     This giveaway was sponsored by the admins of **%2$s**, who acquired **%3$s Telegram Premium** subscriptions for %4$s for its followers.
@@ -7380,21 +7420,11 @@
     On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s**.
     On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s**.
     On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s**.
-    On **%2$s**, Telegram automatically selected **%3$s** random user that joined **%4$s** and **%5$s** other listed channels.
-    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** and **%5$s** other listed channels.
-    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** and **%5$s** other listed channels.
-    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** and **%5$s** other listed channels.
-    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** and **%5$s** other listed channels.
     On **%2$s**, Telegram automatically selected **%3$s** random user that joined **%4$s** after **%5$s** on **%6$s**.
     On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** after **%5$s** on **%6$s**.
     On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** after **%5$s** on **%6$s**.
     On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** after **%5$s** on **%6$s**.
     On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** after **%5$s** on **%6$s**.
-    On **%2$s**, Telegram automatically selected **%3$s** random user that joined **%4$s** and **%5$s** other listed channels after **%6$s** on **%7$s**.
-    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** and **%5$s** other listed channels after **%6$s** on **%7$s**.
-    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** and **%5$s** other listed channels after **%6$s** on **%7$s**.
-    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** and **%5$s** other listed channels after **%6$s** on **%7$s**.
-    On **%2$s**, Telegram automatically selected **%3$s** random users that joined **%4$s** and **%5$s** other listed channels after **%6$s** on **%7$s**.
     Reduce Quantity
     Giveaway ended
     Channel is Private
@@ -7408,30 +7438,70 @@
     **%1$d** of the winners already used their gift links.
     **%1$d** of the winners already used their gift links.
     **%1$d** of the winners already used their gift links.
-    You can’t purchase **%1$d** %2$s subscriptions in the app. Do you want to reduce the prize quantity to **%3$d**?
-    You can’t purchase **%1$d** subscriptions in the app. Only **%2$s** available.
-    Select up to %1$d channels
-    Select up to %1$d countries
+    You can’t purchase **%1$d** %2$s subscription in the app. Do you want to reduce the prize quantity to **%3$d**?
+    You can’t purchase **%1$d** %2$s subscriptions in the app. Do you want to reduce the prize quantity to **%3$d**?
+    You can’t purchase **%1$d** %2$s subscriptions in the app. Do you want to reduce the prize quantity to **%3$d**?
+    You can’t purchase **%1$d** %2$s subscriptions in the app. Do you want to reduce the prize quantity to **%3$d**?
+    You can’t purchase **%1$d** %2$s subscriptions in the app. Do you want to reduce the prize quantity to **%3$d**?
+    You can’t purchase **%1$d** subscription in the app. Only **%2$s** available.
+    You can’t purchase **%1$d** subscriptions in the app. Only **%2$s** available.
+    You can’t purchase **%1$d** subscriptions in the app. Only **%2$s** available.
+    You can’t purchase **%1$d** subscriptions in the app. Only **%2$s** available.
+    You can’t purchase **%1$d** subscriptions in the app. Only **%2$s** available.
+    Select up to %1$d channel
+    Select up to %1$d channels
+    Select up to %1$d channels
+    Select up to %1$d channels
+    Select up to %1$d channels
+    Select up to %1$d country
+    Select up to %1$d countries
+    Select up to %1$d countries
+    Select up to %1$d countries
+    Select up to %1$d countries
     You have changed the list of users. Apply changes?
     You have changed the list of channels. Apply changes?
     You have changed the list of countries. Apply changes?
     You are participating in this giveaway, because you have joined channel **%1$s**.
-    You are participating in this giveaway, because you have joined channel **%1$s** (and **%2$d** other listed channels).
+    You are participating in this giveaway, because you have joined channel **%2$s** (and **%1$d** other listed channel).
+    You are participating in this giveaway, because you have joined channel **%2$s** (and **%1$d** other listed channels).
+    You are participating in this giveaway, because you have joined channel **%2$s** (and **%1$d** other listed channels).
+    You are participating in this giveaway, because you have joined channel **%2$s** (and **%1$d** other listed channels).
+    You are participating in this giveaway, because you have joined channel **%2$s** (and **%1$d** other listed channels).
+    To take part in this giveaway please join channel **%2$s** (and **%1$d** other listed channel) before **%3$s**.
+    To take part in this giveaway please join channel **%2$s** (and **%1$d** other listed channels) before **%3$s**.
+    To take part in this giveaway please join channel **%2$s** (and **%1$d** other listed channels) before **%3$s**.
+    To take part in this giveaway please join channel **%2$s** (and **%1$d** other listed channels) before **%3$s**.
+    To take part in this giveaway please join channel **%2$s** (and **%1$d** other listed channels) before **%3$s**.
     To take part in this giveaway please join channel **%1$s** before **%2$s**.
-    To take part in this giveaway please join channel **%1$s** (and **%2$d** other listed channels) before **%3$s**.
     You are not eligible to participate in this giveaway, because you joined this channel on **%1$s**, which is before the contest started.
     You are not eligible to participate in this giveaway, because you are an admin of participating channel (**%1$s**).
     You are not eligible to participate in this giveaway, because your country is not included in the terms of the giveaway.
     Only the recipient can see the link.
     Only giveaway creator can see the link.
     You can select maximum 10 users.
-    You can select maximum %1$d channels.
-    You can select maximum %1$d countries.
-    Wait until the boost is available or get **%1$d** more boosts by gifting a **Telegram Premium** subscription.
+    You can select maximum %1$d channel.
+    You can select maximum %1$d channels.
+    You can select maximum %1$d channels.
+    You can select maximum %1$d channels.
+    You can select maximum %1$d channels.
+    You can select maximum %1$d country.
+    You can select maximum %1$d countries.
+    You can select maximum %1$d countries.
+    You can select maximum %1$d countries.
+    You can select maximum %1$d countries.
+    Wait until the boost is available or get **%1$d** more boost by gifting a **Telegram Premium** subscription.
+    Wait until the boost is available or get **%1$d** more boosts by gifting a **Telegram Premium** subscription.
+    Wait until the boost is available or get **%1$d** more boosts by gifting a **Telegram Premium** subscription.
+    Wait until the boost is available or get **%1$d** more boosts by gifting a **Telegram Premium** subscription.
+    Wait until the boost is available or get **%1$d** more boosts by gifting a **Telegram Premium** subscription.
     Boost Again
     Reassign Boost
     More Boosts Needed
-    %1$s reassigned from %2$s
+    %1$d boost reassigned from %2$s
+    %1$d boosts reassigned from %2$s
+    %1$d boosts reassigned from %2$s
+    %1$d boosts reassigned from %2$s
+    %1$d boosts reassigned from %2$s
     %d other channels
     %d other channel
     %d other channels
@@ -7440,7 +7510,11 @@
     %d other channels
     To boost **%1$s**, get more boosts by gifting **Telegram Premium** to a friend.
     Reassign Boosts
-    To boost **%1$s**, reassign a previous boost or gift **Telegram Premium** to a friend to get **%2$d** additional boosts.
+    To boost **%2$s**, reassign a previous boost or gift **Telegram Premium** to a friend to get **%1$d** additional boost.
+    To boost **%2$s**, reassign a previous boost or gift **Telegram Premium** to a friend to get **%1$d** additional boosts.
+    To boost **%2$s**, reassign a previous boost or gift **Telegram Premium** to a friend to get **%1$d** additional boosts.
+    To boost **%2$s**, reassign a previous boost or gift **Telegram Premium** to a friend to get **%1$d** additional boosts.
+    To boost **%2$s**, reassign a previous boost or gift **Telegram Premium** to a friend to get **%1$d** additional boosts.
     Remove your boost from
     available in %1$s
     Duration of Premium subscriptions
@@ -7449,10 +7523,21 @@
     from %1$s
     **Winners Selection Date**
     **Giveaway Prizes**
-    **%1$d** Telegram Premium\nSubscription for %2$s.
+    **%1$d** Telegram Premium
+    **%1$d** Telegram Premium
+    **%1$d** Telegram Premium
+    **%1$d** Telegram Premium
+    **%1$d** Telegram Premium
+    Subscription for %2$s.
+    Subscriptions for %2$s.
+    Subscriptions for %2$s.
+    Subscriptions for %2$s.
+    Subscriptions for %2$s.
     **Participants**
-    All subscribers of the channel:
-    New subscribers of the channel:
+    All subscribers of the channel:
+    All subscribers of the channels:
+    New subscribers of the channel:
+    New subscribers of the channels:
     You can’t add up more than 5 reactions tags to a story.
     Someone just got access to your messages!
     Yes, it’s me
@@ -7610,4 +7695,5 @@
     OPEN
     Your name color has been updated!
     Your channel color has been updated!
+    Copy Code
 
diff --git a/gradle.properties b/gradle.properties
index d31d1b985..29279e28e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -13,8 +13,8 @@
 # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
 # org.gradle.parallel=true
 #Sat Mar 12 05:53:50 MSK 2016
-APP_VERSION_CODE=4075
-APP_VERSION_NAME=10.2.3
+APP_VERSION_CODE=4082
+APP_VERSION_NAME=10.2.6
 APP_PACKAGE=org.telegram.messenger
 RELEASE_KEY_PASSWORD=android
 RELEASE_KEY_ALIAS=androidkey