From 1cec9e7b3631fc2a3a4ab0cbc51685c12e7b224a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Thu, 25 Jun 2020 15:28:44 +0000 Subject: [PATCH] Translates --- .../org/telegram/messenger/MessageObject.java | 79 +- .../main/java/org/telegram/tgnet/TLRPC.java | 7 +- .../java/org/telegram/ui/ArticleViewer.java | 272 +++-- .../org/telegram/ui/CacheControlActivity.java | 62 +- .../telegram/ui/Cells/ChatMessageCell.java | 64 +- .../ui/Cells/TextSelectionHelper.java | 64 +- .../java/org/telegram/ui/ChatActivity.java | 929 ++++++++++-------- .../ui/Components/ChatActivityEnterView.java | 224 ++++- .../ui/Components/ChatAttachAlert.java | 129 ++- .../ui/Components/EditTextCaption.java | 79 +- .../telegram/ui/PhotoAlbumPickerActivity.java | 115 ++- .../org/telegram/ui/PhotoPickerActivity.java | 118 ++- .../java/org/telegram/ui/PhotoViewer.java | 338 +++++-- .../nekomimi/nekogram/parts/ArticleTrans.kt | 202 ++++ .../nekomimi/nekogram/parts/MessageTrans.kt | 328 +++++++ .../nekogram/transtale/ChatLanguage.java | 37 + .../nekogram/transtale/TransItem.java | 40 + .../nekogram/transtale/TransUtils.java | 80 ++ .../transtale/TranslateBottomSheet.java | 211 ++++ .../nekogram/transtale/TranslateDb.kt | 72 ++ .../nekomimi/nekogram/transtale/Translator.kt | 207 ++++ .../transtale/source/GoogleCloudTranslator.kt | 73 ++ .../transtale/source/GoogleWebTranslator.kt | 90 ++ .../transtale/source/LingoTranslator.kt | 52 + .../transtale/source/YandexTranslator.kt | 48 + 25 files changed, 3178 insertions(+), 742 deletions(-) create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/ArticleTrans.kt create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/MessageTrans.kt create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/ChatLanguage.java create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TransItem.java create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TransUtils.java create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TranslateBottomSheet.java create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TranslateDb.kt create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/Translator.kt create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/GoogleCloudTranslator.kt create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/GoogleWebTranslator.kt create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/LingoTranslator.kt create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/YandexTranslator.kt diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index c64cf4988..6e9f8f5dc 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -57,7 +57,8 @@ import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; -import tw.nekomimi.nekogram.NekoConfig; +import cn.hutool.core.util.StrUtil; +import tw.nekomimi.nekogram.NekoXConfig; public class MessageObject { @@ -131,9 +132,6 @@ public class MessageObject { public boolean scheduled; - public boolean translated; - public Object originalMessage; - public ArrayList checkedVotes; public CharSequence editingMessage; @@ -1671,14 +1669,22 @@ public class MessageObject { } public void applyNewText() { - if (TextUtils.isEmpty(messageOwner.message)) { + + if (StrUtil.isBlank(messageOwner.message) || (messageOwner.translated && StrUtil.isBlank(messageOwner.translatedMessage))) { return; } + TLRPC.User fromUser = null; if (isFromUser()) { fromUser = MessagesController.getInstance(currentAccount).getUser(messageOwner.from_id); } - messageText = messageOwner.message; + + if (messageOwner.translated) { + messageText = messageOwner.translatedMessage; + } else { + messageText = messageOwner.message; + } + TextPaint paint; if (messageOwner.media instanceof TLRPC.TL_messageMediaGame) { paint = Theme.chat_msgGameTextPaint; @@ -2388,7 +2394,7 @@ public class MessageObject { if (messageOwner.from_id == UserConfig.getInstance(currentAccount).getClientUserId()) { if (isMissed) { messageText = LocaleController.getString("CallMessageOutgoingMissed", R.string.CallMessageOutgoingMissed); - }else { + } else { messageText = LocaleController.getString("CallMessageOutgoing", R.string.CallMessageOutgoing); } } else { @@ -2534,7 +2540,7 @@ public class MessageObject { } else if (messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) { messageText = messageOwner.media.description; } else if (messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported) { - messageText = LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia).replace("https://telegram.org/update", "https://play.google.com/store/apps/details?id=tw.nekomimi.nekogram"); + messageText = LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia).replace("https://telegram.org/update", "https://github.com/NekoX-Dev/NekoX"); } else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { if (isSticker() || isAnimatedStickerDocument(getDocument(), true)) { String sch = getStickerChar(); @@ -3186,8 +3192,16 @@ public class MessageObject { if (caption != null || isRoundVideo()) { return; } - if (!isMediaEmpty() && !(messageOwner.media instanceof TLRPC.TL_messageMediaGame) && !TextUtils.isEmpty(messageOwner.message)) { - caption = Emoji.replaceEmoji(messageOwner.message, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + if (!isMediaEmpty() && !(messageOwner.media instanceof TLRPC.TL_messageMediaGame) && StrUtil.isNotBlank(messageOwner.message) && (!messageOwner.translated || StrUtil.isNotBlank(messageOwner.translatedMessage))) { + + String msg; + if (messageOwner.translated) { + msg = messageOwner.translatedMessage; + } else { + msg = messageOwner.message; + } + + caption = Emoji.replaceEmoji(msg, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); boolean hasEntities; if (messageOwner.send_state != MESSAGE_SEND_STATE_SENT) { @@ -3224,6 +3238,12 @@ public class MessageObject { addUrlsByPattern(isOutOwner(), caption, true, 0, 0, true); } + try { + AndroidUtilities.addProxyLinks((Spannable) caption); + } catch (Exception e) { + FileLog.e(e); + } + addEntitiesToText(caption, useManualParse); if (isVideo()) { addUrlsByPattern(isOutOwner(), caption, true, 3, getDuration(), false); @@ -3757,16 +3777,16 @@ public class MessageObject { boolean useManualParse = !hasEntities && ( eventId != 0 || - messageOwner instanceof TLRPC.TL_message_old || - messageOwner instanceof TLRPC.TL_message_old2 || - messageOwner instanceof TLRPC.TL_message_old3 || - messageOwner instanceof TLRPC.TL_message_old4 || - messageOwner instanceof TLRPC.TL_messageForwarded_old || - messageOwner instanceof TLRPC.TL_messageForwarded_old2 || - messageOwner instanceof TLRPC.TL_message_secret || - messageOwner.media instanceof TLRPC.TL_messageMediaInvoice || - isOut() && messageOwner.send_state != MESSAGE_SEND_STATE_SENT || - messageOwner.id < 0 || messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported); + messageOwner instanceof TLRPC.TL_message_old || + messageOwner instanceof TLRPC.TL_message_old2 || + messageOwner instanceof TLRPC.TL_message_old3 || + messageOwner instanceof TLRPC.TL_message_old4 || + messageOwner instanceof TLRPC.TL_messageForwarded_old || + messageOwner instanceof TLRPC.TL_messageForwarded_old2 || + messageOwner instanceof TLRPC.TL_message_secret || + messageOwner.media instanceof TLRPC.TL_messageMediaInvoice || + isOut() && messageOwner.send_state != MESSAGE_SEND_STATE_SENT || + messageOwner.id < 0 || messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported); if (useManualParse) { addLinks(isOutOwner(), messageText, true, true); @@ -3779,6 +3799,11 @@ public class MessageObject { } } } + try { + AndroidUtilities.addProxyLinks((Spannable) messageText); + } catch (Throwable e) { + FileLog.e(e); + } if (isYouTubeVideo() || replyMessageObject != null && replyMessageObject.isYouTubeVideo()) { addUrlsByPattern(isOutOwner(), messageText, false, 3, Integer.MAX_VALUE, false); } else if (replyMessageObject != null) { @@ -4129,7 +4154,7 @@ public class MessageObject { } public static boolean shouldEncryptPhotoOrVideo(TLRPC.Message message) { - if (NekoConfig.shouldNOTTrustMe) { + if (NekoXConfig.disableFlagSecure) { return false; } if (message instanceof TLRPC.TL_message_secret) { @@ -4144,7 +4169,7 @@ public class MessageObject { } public static boolean isSecretPhotoOrVideo(TLRPC.Message message) { - if (NekoConfig.shouldNOTTrustMe) { + if (NekoXConfig.disableFlagSecure) { return false; } if (message instanceof TLRPC.TL_message_secret) { @@ -4156,7 +4181,7 @@ public class MessageObject { } public static boolean isSecretMedia(TLRPC.Message message) { - if (NekoConfig.shouldNOTTrustMe) { + if (NekoXConfig.disableFlagSecure) { return false; } if (message instanceof TLRPC.TL_message_secret) { @@ -4168,7 +4193,7 @@ public class MessageObject { } public boolean needDrawBluredPreview() { - if (NekoConfig.shouldNOTTrustMe) { + if (NekoXConfig.disableFlagSecure) { return false; } if (messageOwner instanceof TLRPC.TL_message_secret) { @@ -4181,7 +4206,7 @@ public class MessageObject { } public boolean isSecretMedia() { - if (NekoConfig.shouldNOTTrustMe) { + if (NekoXConfig.disableFlagSecure) { return false; } if (messageOwner instanceof TLRPC.TL_message_secret) { @@ -4661,7 +4686,7 @@ public class MessageObject { } if (photoHeight > maxHeight) { photoWidth *= maxHeight / photoHeight; - photoHeight = (int)maxHeight; + photoHeight = (int) maxHeight; } if (photoWidth > maxWidth) { photoHeight *= maxWidth / photoWidth; @@ -5065,7 +5090,7 @@ public class MessageObject { } public boolean canForwardMessage() { - return !(messageOwner instanceof TLRPC.TL_message_secret) && !needDrawBluredPreview() && !isLiveLocation() && type != 16; + return NekoXConfig.disableFlagSecure || !(messageOwner instanceof TLRPC.TL_message_secret) && !needDrawBluredPreview() && !isLiveLocation() && type != 16; } public boolean canEditMedia() { diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index 779f667de..b5d6de80e 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -1941,6 +1941,8 @@ public class TLRPC { public String text; public byte[] option; + public String translatedText; // custom + public static TL_pollAnswer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { if (TL_pollAnswer.constructor != constructor) { if (exception) { @@ -25066,6 +25068,8 @@ public class TLRPC { public int close_period; public int close_date; + public String translatedQuestion; // custom + public static Poll TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Poll result = null; switch (constructor) { @@ -41404,7 +41408,8 @@ public class TLRPC { public int reqId; //custom public int realId; //custom public int stickerVerified = 1; //custom - + public String translatedMessage; //custom + public boolean translated; // custom public static Message TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Message result = null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 51ec761f8..491d97e02 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -107,6 +107,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; +import org.jetbrains.annotations.NotNull; import org.json.JSONObject; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -137,6 +138,7 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; @@ -188,7 +190,13 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; +import cn.hutool.core.util.StrUtil; import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.parts.ArticleTransKt; +import tw.nekomimi.nekogram.transtale.TranslateDb; +import tw.nekomimi.nekogram.transtale.Translator; +import tw.nekomimi.nekogram.utils.AlertUtil; +import tw.nekomimi.nekogram.utils.ProxyUtil; import static org.telegram.messenger.MessageObject.POSITION_FLAG_BOTTOM; import static org.telegram.messenger.MessageObject.POSITION_FLAG_LEFT; @@ -197,7 +205,7 @@ import static org.telegram.messenger.MessageObject.POSITION_FLAG_TOP; public class ArticleViewer implements NotificationCenter.NotificationCenterDelegate, GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener { - private Activity parentActivity; + public Activity parentActivity; private BaseFragment parentFragment; private ArrayList createdWebViews = new ArrayList<>(); @@ -216,7 +224,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private boolean isVisible; private boolean collapsed; private boolean attachedToWindow; - + private int currentAccount; private int lastBlockNum = 1; @@ -265,7 +273,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private RecyclerListView[] listView; private LinearLayoutManager[] layoutManager; - private WebpageAdapter[] adapter; + public WebpageAdapter[] adapter; private AnimatorSet pageSwitchAnimation; @@ -304,9 +312,12 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private LinkPath urlPath = new LinkPath(); private static final int search_item = 1; - private static final int share_item = 2; - private static final int open_item = 3; - private static final int settings_item = 4; + private static final int trans_item = 2; + private static final int share_item = 3; + private static final int open_item = 4; + private static final int settings_item = 5; + + public ActionBarMenuSubItem transMenu; private int anchorsOffsetMeasuredWidth; @@ -526,7 +537,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg SharedPreferences preferences = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); editor.putInt("iv_font_size", SharedConfig.ivFontSize); - editor.commit(); + editor.apply(); adapter[0].searchTextOffset.clear(); updatePaintSize(); invalidate(); @@ -1741,7 +1752,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg builder.setDelegate(new BottomSheet.BottomSheetDelegate() { @Override public boolean canDismiss() { - if (textSelectionHelperBottomSheet != null && textSelectionHelperBottomSheet.isSelectionMode()){ + if (textSelectionHelperBottomSheet != null && textSelectionHelperBottomSheet.isSelectionMode()) { textSelectionHelperBottomSheet.clear(); return false; } @@ -1945,7 +1956,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } else if (richText instanceof TLRPC.TL_textUrl) { return getLastRichText(((TLRPC.TL_textUrl) richText).text); } else if (richText instanceof TLRPC.TL_textAnchor) { - getLastRichText(((TLRPC.TL_textAnchor) richText).text); + return getLastRichText(((TLRPC.TL_textAnchor) richText).text); } else if (richText instanceof TLRPC.TL_textSubscript) { return getLastRichText(((TLRPC.TL_textSubscript) richText).text); } else if (richText instanceof TLRPC.TL_textSuperscript) { @@ -1959,21 +1970,27 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } private CharSequence getText(WebpageAdapter adapter, View parentView, TLRPC.RichText parentRichText, TLRPC.RichText richText, TLRPC.PageBlock parentBlock, int maxWidth) { + + return getText(adapter, parentView, parentRichText, richText, parentBlock, maxWidth, false); + + } + + public CharSequence getText(WebpageAdapter adapter, View parentView, TLRPC.RichText parentRichText, TLRPC.RichText richText, TLRPC.PageBlock parentBlock, int maxWidth, boolean noTranslate) { if (richText == null) { return null; } if (richText instanceof TLRPC.TL_textFixed) { - return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textFixed) richText).text, parentBlock, maxWidth); + return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textFixed) richText).text, parentBlock, maxWidth, noTranslate); } else if (richText instanceof TLRPC.TL_textItalic) { - return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textItalic) richText).text, parentBlock, maxWidth); + return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textItalic) richText).text, parentBlock, maxWidth, noTranslate); } else if (richText instanceof TLRPC.TL_textBold) { - return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textBold) richText).text, parentBlock, maxWidth); + return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textBold) richText).text, parentBlock, maxWidth, noTranslate); } else if (richText instanceof TLRPC.TL_textUnderline) { - return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textUnderline) richText).text, parentBlock, maxWidth); + return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textUnderline) richText).text, parentBlock, maxWidth, noTranslate); } else if (richText instanceof TLRPC.TL_textStrike) { - return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textStrike) richText).text, parentBlock, maxWidth); + return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textStrike) richText).text, parentBlock, maxWidth, noTranslate); } else if (richText instanceof TLRPC.TL_textEmail) { - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(adapter, parentView, parentRichText, ((TLRPC.TL_textEmail) richText).text, parentBlock, maxWidth)); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(adapter, parentView, parentRichText, ((TLRPC.TL_textEmail) richText).text, parentBlock, maxWidth, noTranslate)); MetricAffectingSpan[] innerSpans = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); if (spannableStringBuilder.length() != 0) { spannableStringBuilder.setSpan(new TextPaintUrlSpan(innerSpans == null || innerSpans.length == 0 ? getTextPaint(parentRichText, richText, parentBlock) : null, "mailto:" + getUrl(richText)), 0, spannableStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); @@ -1981,7 +1998,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return spannableStringBuilder; } else if (richText instanceof TLRPC.TL_textUrl) { TLRPC.TL_textUrl textUrl = (TLRPC.TL_textUrl) richText; - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(adapter, parentView, parentRichText, ((TLRPC.TL_textUrl) richText).text, parentBlock, maxWidth)); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(adapter, parentView, parentRichText, ((TLRPC.TL_textUrl) richText).text, parentBlock, maxWidth, noTranslate)); MetricAffectingSpan[] innerSpans = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); TextPaint paint = innerSpans == null || innerSpans.length == 0 ? getTextPaint(parentRichText, richText, parentBlock) : null; MetricAffectingSpan span; @@ -1995,10 +2012,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } return spannableStringBuilder; } else if (richText instanceof TLRPC.TL_textPlain) { - return ((TLRPC.TL_textPlain) richText).text; + String plainText = ((TLRPC.TL_textPlain) richText).text; + if (!noTranslate && StrUtil.isNotBlank(plainText) && adapter.trans && TranslateDb.currentTarget().contains(plainText)) { + plainText = TranslateDb.currentTarget().query(plainText); + } + return plainText; } else if (richText instanceof TLRPC.TL_textAnchor) { TLRPC.TL_textAnchor textAnchor = (TLRPC.TL_textAnchor) richText; - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(adapter, parentView, parentRichText, textAnchor.text, parentBlock, maxWidth)); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(adapter, parentView, parentRichText, textAnchor.text, parentBlock, maxWidth, noTranslate)); spannableStringBuilder.setSpan(new AnchorSpan(textAnchor.name), 0, spannableStringBuilder.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); return spannableStringBuilder; } else if (richText instanceof TLRPC.TL_textEmpty) { @@ -2015,7 +2036,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg spannableStringBuilder.setSpan(new TextSelectionHelper.IgnoreCopySpannable(), spannableStringBuilder.length() - 1, spannableStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - CharSequence innerText = getText(adapter, parentView, parentRichText, innerRichText, parentBlock, maxWidth); + CharSequence innerText = getText(adapter, parentView, parentRichText, innerRichText, parentBlock, maxWidth, noTranslate); int flags = getTextFlags(lastRichText); int startLength = spannableStringBuilder.length(); spannableStringBuilder.append(innerText); @@ -2047,18 +2068,18 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } return spannableStringBuilder; } else if (richText instanceof TLRPC.TL_textSubscript) { - return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textSubscript) richText).text, parentBlock, maxWidth); + return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textSubscript) richText).text, parentBlock, maxWidth, noTranslate); } else if (richText instanceof TLRPC.TL_textSuperscript) { - return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textSuperscript) richText).text, parentBlock, maxWidth); + return getText(adapter, parentView, parentRichText, ((TLRPC.TL_textSuperscript) richText).text, parentBlock, maxWidth, noTranslate); } else if (richText instanceof TLRPC.TL_textMarked) { - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(adapter, parentView, parentRichText, ((TLRPC.TL_textMarked) richText).text, parentBlock, maxWidth)); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(adapter, parentView, parentRichText, ((TLRPC.TL_textMarked) richText).text, parentBlock, maxWidth, noTranslate)); MetricAffectingSpan[] innerSpans = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); if (spannableStringBuilder.length() != 0) { spannableStringBuilder.setSpan(new TextPaintMarkSpan(innerSpans == null || innerSpans.length == 0 ? getTextPaint(parentRichText, richText, parentBlock) : null), 0, spannableStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } return spannableStringBuilder; } else if (richText instanceof TLRPC.TL_textPhone) { - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(adapter, parentView, parentRichText, ((TLRPC.TL_textPhone) richText).text, parentBlock, maxWidth)); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(adapter, parentView, parentRichText, ((TLRPC.TL_textPhone) richText).text, parentBlock, maxWidth, noTranslate)); MetricAffectingSpan[] innerSpans = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); if (spannableStringBuilder.length() != 0) { spannableStringBuilder.setSpan(new TextPaintUrlSpan(innerSpans == null || innerSpans.length == 0 ? getTextPaint(parentRichText, richText, parentBlock) : null, "tel:" + getUrl(richText)), 0, spannableStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); @@ -2109,7 +2130,11 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } else if (richText instanceof TLRPC.TL_textUrl) { return getPlainText(((TLRPC.TL_textUrl) richText).text); } else if (richText instanceof TLRPC.TL_textPlain) { - return ((TLRPC.TL_textPlain) richText).text; + String plainText = ((TLRPC.TL_textPlain) richText).text; + if (plainText != null && Instance != null && Instance.adapter[0].trans && TranslateDb.currentTarget().contains(plainText)) { + plainText = TranslateDb.currentTarget().query(plainText); + } + return plainText; } else if (richText instanceof TLRPC.TL_textAnchor) { return getPlainText(((TLRPC.TL_textAnchor) richText).text); } else if (richText instanceof TLRPC.TL_textEmpty) { @@ -2150,7 +2175,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return ((TLRPC.TL_textEmail) richText).email; } else if (richText instanceof TLRPC.TL_textUrl) { return ((TLRPC.TL_textUrl) richText).url; - }else if (richText instanceof TLRPC.TL_textPhone) { + } else if (richText instanceof TLRPC.TL_textPhone) { return ((TLRPC.TL_textPhone) richText).phone; } return null; @@ -2421,7 +2446,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg CharSequence text; if (plainText != null) { - text = plainText; + text = (parentAdapter.trans && TranslateDb.currentTarget().contains(plainText.toString())) ? TranslateDb.currentTarget().query(plainText.toString()) : plainText; } else { text = getText(parentAdapter, parentView, richText, richText, parentBlock, width); } @@ -2893,14 +2918,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - private void updatePaintSize() { + public void updatePaintSize() { for (int i = 0; i < 2; i++) { adapter[i].notifyDataSetChanged(); } } private void updatePaintFonts() { - ApplicationLoader.applicationContext.getSharedPreferences("articles", Activity.MODE_PRIVATE).edit().putInt("font_type", selectedFont).commit(); + ApplicationLoader.applicationContext.getSharedPreferences("articles", Activity.MODE_PRIVATE).edit().putInt("font_type", selectedFont).apply(); Typeface typefaceNormal = selectedFont == 0 ? Typeface.DEFAULT : Typeface.SERIF; Typeface typefaceItalic = selectedFont == 0 ? AndroidUtilities.getTypeface("fonts/ritalic.ttf") : Typeface.create("serif", Typeface.ITALIC); Typeface typefaceBold = selectedFont == 0 ? AndroidUtilities.getTypeface("fonts/rmedium.ttf") : Typeface.create("serif", Typeface.BOLD); @@ -3053,7 +3078,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg parentActivity = activity; SharedPreferences sharedPreferences = ApplicationLoader.applicationContext.getSharedPreferences("articles", Activity.MODE_PRIVATE); - selectedFont = sharedPreferences.getInt("font_type", 0); + selectedFont = sharedPreferences.getInt("font_type", 1); createPaint(false); backgroundPaint = new Paint(); @@ -3555,7 +3580,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } }; clearButton.setImageDrawable(new CloseProgressDrawable2()); - clearButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + clearButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); clearButton.setScaleType(ImageView.ScaleType.CENTER); clearButton.setAlpha(0.0f); clearButton.setRotation(45); @@ -3607,10 +3632,13 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg menuButton.setDuplicateParentStateEnabled(false); menuButton.setClickable(true); menuButton.setIcon(R.drawable.ic_ab_other); - menuButton.addSubItem(search_item, R.drawable.msg_search, LocaleController.getString("Search", R.string.Search)); - menuButton.addSubItem(share_item, R.drawable.msg_share, LocaleController.getString("ShareFile", R.string.ShareFile)); - menuButton.addSubItem(open_item, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)); - menuButton.addSubItem(settings_item, R.drawable.menu_settings, LocaleController.getString("Settings", R.string.Settings)); + menuButton.addSubItem(search_item, R.drawable.baseline_search_24, LocaleController.getString("Search", R.string.Search)); + + transMenu = menuButton.addSubItem(trans_item, R.drawable.ic_translate, LocaleController.getString("Translate", R.string.Translate)); + + menuButton.addSubItem(share_item, R.drawable.baseline_share_24, LocaleController.getString("ShareFile", R.string.ShareFile)); + menuButton.addSubItem(open_item, R.drawable.baseline_open_in_browser_24, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)); + menuButton.addSubItem(settings_item, R.drawable.baseline_settings_24, LocaleController.getString("Settings", R.string.Settings)); menuButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); menuButton.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); menuContainer.addView(menuButton, LayoutHelper.createFrame(48, 56)); @@ -3624,6 +3652,16 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } if (id == search_item) { showSearch(true); + } else if (id == trans_item) { + if (!adapter[0].trans) { + adapter[0].trans = true; + transMenu.setTextAndIcon(LocaleController.getString("UndoTranslate", R.string.UndoTranslate), R.drawable.photo_undo); + ArticleTransKt.doTransLATE(this); + } else { + adapter[0].trans = false; + transMenu.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate); + updatePaintSize(); + } } else if (id == share_item) { showDialog(new ShareAlert(parentActivity, null, adapter[0].currentPage.url, false, adapter[0].currentPage.url, false)); } else if (id == open_item) { @@ -3709,7 +3747,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg searchUpButton = new ImageView(parentActivity); searchUpButton.setScaleType(ImageView.ScaleType.CENTER); searchUpButton.setImageResource(R.drawable.msg_go_up); - searchUpButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + searchUpButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); searchUpButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchPanel.addView(searchUpButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 48, 0)); searchUpButton.setOnClickListener(view -> scrollToSearchIndex(currentSearchIndex - 1)); @@ -3718,7 +3756,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg searchDownButton = new ImageView(parentActivity); searchDownButton.setScaleType(ImageView.ScaleType.CENTER); searchDownButton.setImageResource(R.drawable.msg_go_down); - searchDownButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + searchDownButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); searchDownButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchPanel.addView(searchDownButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 0, 0)); searchDownButton.setOnClickListener(view -> scrollToSearchIndex(currentSearchIndex + 1)); @@ -3784,7 +3822,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg MediaController.saveFile(f.toString(), parentActivity, isMediaVideo(photoAdapter, currentIndex) ? 1 : 0, null, null); } else { AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setMessage(LocaleController.getString("PleaseDownload", R.string.PleaseDownload)); showDialog(builder.create()); @@ -3805,6 +3843,41 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000)); MessagesController.getInstance(currentAccount).saveGif(adapter[0].currentPage, document); } + } else if (id == gallery_menu_scan) { + + boolean isVideo = imagesArr.get(currentIndex) instanceof TLRPC.TL_pageBlockVideo; + + try { + + if (isVideo) { + + ProxyUtil.tryReadQR(parentActivity, videoTextureView.getBitmap()); + + } else { + + File f = getMediaFile(photoAdapter, currentIndex); + + if (f != null && f.exists()) { + + Bitmap bitmap = ImageLoader.loadBitmap(f.getPath(), null, -1f, -1f, false); + + ProxyUtil.tryReadQR(parentActivity, bitmap); + + } else { + AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setMessage(LocaleController.getString("PleaseDownload", R.string.PleaseDownload)); + showDialog(builder.create()); + } + + } + + } catch (Exception ignored) { + + AlertUtil.showToast(LocaleController.getString("NoQrFound", R.string.NoQrFound)); + + } } } @@ -3817,13 +3890,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg ActionBarMenu menu = actionBar.createMenu(); - menu.addItem(gallery_menu_share, R.drawable.share); + menu.addItem(gallery_menu_share, R.drawable.baseline_share_24); menuItem = menu.addItem(0, R.drawable.ic_ab_other); menuItem.setLayoutInScreen(true); - menuItem.addSubItem(gallery_menu_openin, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_openin, R.drawable.baseline_open_in_browser_24, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)).setColors(0xfffafafa, 0xfffafafa); //menuItem.addSubItem(gallery_menu_share, LocaleController.getString("ShareFile", R.string.ShareFile), 0).setTextColor(0xfffafafa); - menuItem.addSubItem(gallery_menu_save, R.drawable.msg_gallery, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_savegif, R.drawable.msg_gif, LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_save, R.drawable.baseline_image_24, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_savegif, R.drawable.deproko_baseline_gif_24, LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_scan, R.drawable.wallet_qr, LocaleController.getString("ScanQRCode", R.string.ScanQRCode)).setColors(0xfffafafa, 0xfffafafa); menuItem.redrawPopup(0xf9222222); bottomLayout = new FrameLayout(parentActivity); @@ -4202,9 +4276,6 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (object instanceof TLRPC.RichText) { TLRPC.RichText richText = (TLRPC.RichText) object; CharSequence innerText = getText(adapter[0], null, richText, richText, block, 1000); - if (!TextUtils.isEmpty(innerText)) { - textToSearchIn = innerText.toString().toLowerCase(); - } } else if (object instanceof String) { textToSearchIn = ((String) object).toLowerCase(); } @@ -4474,7 +4545,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } pagesStack.set(0, webPage); if (pagesStack.size() == 1) { - ApplicationLoader.applicationContext.getSharedPreferences("articles", Activity.MODE_PRIVATE).edit().remove("article" + webPage.id).commit(); + ApplicationLoader.applicationContext.getSharedPreferences("articles", Activity.MODE_PRIVATE).edit().remove("article" + webPage.id).apply(); updateInterfaceForCurrentPage(webPage, false, 0); if (anchorFinal != null) { scrollToAnchor(anchorFinal); @@ -4802,7 +4873,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } SharedPreferences.Editor editor = ApplicationLoader.applicationContext.getSharedPreferences("articles", Activity.MODE_PRIVATE).edit(); String key = "article" + adapter[0].currentPage.id; - editor.putInt(key, position).putInt(key + "o", offset).putBoolean(key + "r", AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y).commit(); + editor.putInt(key, position).putInt(key + "o", offset).putBoolean(key + "r", AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y).apply(); } } @@ -4823,11 +4894,11 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg searchField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); } if (searchUpButton != null) { - searchUpButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + searchUpButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); searchUpButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); } if (searchDownButton != null) { - searchDownButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + searchDownButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); searchDownButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); } if (searchCountText != null) { @@ -4839,7 +4910,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg menuButton.setPopupItemsColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon), true); } if (clearButton != null) { - clearButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + clearButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); } if (backDrawable != null) { backDrawable.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); @@ -4856,7 +4927,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg customViewCallback.onCustomViewHidden(); fullscreenVideoContainer.removeView(customView); customView = null; - } else if (fullscreenedVideo != null) { + } else if (fullscreenedVideo != null) { fullscreenedVideo.exitFullscreen(); } if (!force) { @@ -5109,7 +5180,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - private class WebpageAdapter extends RecyclerListView.SelectionAdapter { + public class WebpageAdapter extends RecyclerListView.SelectionAdapter { private Context context; private ArrayList localBlocks = new ArrayList<>(); @@ -5120,14 +5191,16 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private HashMap anchorsParent = new HashMap<>(); private HashMap audioBlocks = new HashMap<>(); private ArrayList audioMessages = new ArrayList<>(); - private HashMap textToBlocks = new HashMap<>(); - private ArrayList textBlocks = new ArrayList<>(); + public HashMap textToBlocks = new HashMap<>(); + public ArrayList textBlocks = new ArrayList<>(); private HashMap searchTextOffset = new HashMap<>(); private TLRPC.WebPage currentPage; private TLRPC.TL_pageBlockChannel channelBlock; private boolean isRtl; + public boolean trans; + public WebpageAdapter(Context ctx) { context = ctx; } @@ -6138,6 +6211,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } private void cleanup() { + trans = false; + transMenu.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate); currentPage = null; blocks.clear(); photoBlocks.clear(); @@ -7095,7 +7170,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } nameLayout = createLayoutForText(this, currentBlock.author, null, width - AndroidUtilities.dp(36 + 14 + (avatarVisible ? 40 + 14 : 0)), 0, currentBlock, Layout.Alignment.ALIGN_NORMAL, 1, parentAdapter); - if (nameLayout != null){ + if (nameLayout != null) { nameLayout.x = AndroidUtilities.dp(18 + 14 + (avatarVisible ? 40 + 14 : 0)); nameLayout.y = AndroidUtilities.dp(dateLayout != null ? 10 : 19); } @@ -8015,7 +8090,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - private class BlockCollageCell extends FrameLayout implements TextSelectionHelper.ArticleSelectableView{ + private class BlockCollageCell extends FrameLayout implements TextSelectionHelper.ArticleSelectableView { private RecyclerListView innerListView; private RecyclerView.Adapter innerAdapter; @@ -8047,18 +8122,18 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg public float[] heights; public MessageGroupedLayoutAttempt(int i1, int i2, float f1, float f2) { - lineCounts = new int[] {i1, i2}; - heights = new float[] {f1, f2}; + lineCounts = new int[]{i1, i2}; + heights = new float[]{f1, f2}; } public MessageGroupedLayoutAttempt(int i1, int i2, int i3, float f1, float f2, float f3) { - lineCounts = new int[] {i1, i2, i3}; - heights = new float[] {f1, f2, f3}; + lineCounts = new int[]{i1, i2, i3}; + heights = new float[]{f1, f2, f3}; } public MessageGroupedLayoutAttempt(int i1, int i2, int i3, int i4, float f1, float f2, float f3, float f4) { - lineCounts = new int[] {i1, i2, i3, i4}; - heights = new float[] {f1, f2, f3, f4}; + lineCounts = new int[]{i1, i2, i3, i4}; + heights = new float[]{f1, f2, f3, f4}; } } @@ -8180,7 +8255,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg position3.set(0, 1, 1, 1, rightWidth, thirdHeight / maxSizeHeight, POSITION_FLAG_RIGHT | POSITION_FLAG_BOTTOM); position3.spanSize = maxSizeWidth; - position1.siblingHeights = new float[] {thirdHeight / maxSizeHeight, secondHeight / maxSizeHeight}; + position1.siblingHeights = new float[]{thirdHeight / maxSizeHeight, secondHeight / maxSizeHeight}; position2.spanSize = maxSizeWidth - leftWidth; position3.leftSpanOffset = leftWidth; @@ -8234,7 +8309,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg position3.leftSpanOffset = w0; position4.leftSpanOffset = w0; - position1.siblingHeights = new float[] {h0, h1, h2}; + position1.siblingHeights = new float[]{h0, h1, h2}; hasSibling = true; } } @@ -8291,7 +8366,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg MessageGroupedLayoutAttempt attempt = attempts.get(a); float height = 0; float minLineHeight = Float.MAX_VALUE; - for (int b = 0; b < attempt.heights.length; b++){ + for (int b = 0; b < attempt.heights.length; b++) { height += attempt.heights[b]; if (attempt.heights[b] < minLineHeight) { minLineHeight = attempt.heights[b]; @@ -9084,7 +9159,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (textLayout != null) { canvas.save(); canvas.translate(textX, textY); - drawTextSelection(canvas,this); + drawTextSelection(canvas, this); textLayout.draw(canvas); canvas.restore(); } @@ -9282,8 +9357,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg ((TextSelectionHelper.ArticleSelectableView) blockLayout.itemView).fillTextLayoutBlocks(textSelectionHelper.arrayList); for (TextSelectionHelper.TextLayoutBlock block : textSelectionHelper.arrayList) { if (block instanceof DrawingText) { - ((DrawingText)block).x += blockX; - ((DrawingText)block).y += blockY; + ((DrawingText) block).x += blockX; + ((DrawingText) block).y += blockY; } } } @@ -9429,7 +9504,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (textLayout != null) { canvas.save(); canvas.translate(textX, textY); - drawTextSelection(canvas,this); + drawTextSelection(canvas, this); textLayout.draw(canvas); canvas.restore(); } @@ -10343,14 +10418,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (captionLayout != null) { canvas.save(); canvas.translate(textX, textY); - drawTextSelection(canvas,this, count++); + drawTextSelection(canvas, this, count++); captionLayout.draw(canvas); canvas.restore(); } if (creditLayout != null) { canvas.save(); canvas.translate(textX, textY + creditOffset); - drawTextSelection(canvas,this, count); + drawTextSelection(canvas, this, count); creditLayout.draw(canvas); canvas.restore(); } @@ -10744,11 +10819,11 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg int b = Color.blue(color); textView.setTextColor(getLinkTextColor()); backgroundPaint.setColor(Color.argb(34, r, g, b)); - imageView.setColorFilter(new PorterDuffColorFilter(getGrayTextColor(), PorterDuff.Mode.MULTIPLY)); + imageView.setColorFilter(new PorterDuffColorFilter(getGrayTextColor(), PorterDuff.Mode.SRC_IN)); } else { textView.setTextColor(0xffffffff); backgroundPaint.setColor(0x7f000000); - imageView.setColorFilter(new PorterDuffColorFilter(0xffffffff, PorterDuff.Mode.MULTIPLY)); + imageView.setColorFilter(new PorterDuffColorFilter(0xffffffff, PorterDuff.Mode.SRC_IN)); } TLRPC.Chat channel = MessagesController.getInstance(currentAccount).getChat(block.channel.id); if (channel == null || channel.min) { @@ -10912,12 +10987,17 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg spannableAuthor = null; spans = null; } - if (currentBlock.published_date != 0 && !TextUtils.isEmpty(author)) { - text = LocaleController.formatString("ArticleDateByAuthor", R.string.ArticleDateByAuthor, LocaleController.getInstance().chatFullDate.format((long) currentBlock.published_date * 1000), author); - } else if (!TextUtils.isEmpty(author)) { - text = LocaleController.formatString("ArticleByAuthor", R.string.ArticleByAuthor, author); - } else { - text = LocaleController.getInstance().chatFullDate.format((long) currentBlock.published_date * 1000); + try { + if (currentBlock.published_date != 0 && !TextUtils.isEmpty(author)) { + text = LocaleController.formatString("ArticleDateByAuthor", R.string.ArticleDateByAuthor, LocaleController.getInstance().chatFullDate.format((long) currentBlock.published_date * 1000), author); + } else if (!TextUtils.isEmpty(author)) { + text = LocaleController.formatString("ArticleByAuthor", R.string.ArticleByAuthor, author); + } else { + text = LocaleController.getInstance().chatFullDate.format((long) currentBlock.published_date * 1000); + } + } catch (Exception e) { + FileLog.e(e); + text = "Nya ~"; } try { if (spans != null && spans.length > 0) { @@ -10965,14 +11045,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setEnabled(true); + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); if (textLayout == null) return; - info.setText(textLayout.getText()); - } + info.setText(textLayout.getText()); + } @Override public void fillTextLayoutBlocks(ArrayList blocks) { @@ -11041,7 +11121,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (textLayout != null) { canvas.save(); canvas.translate(textX, textY); - drawTextSelection(canvas,this); + drawTextSelection(canvas, this); textLayout.draw(canvas); canvas.restore(); } @@ -11342,7 +11422,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - private class BlockSubheaderCell extends View implements TextSelectionHelper.ArticleSelectableView{ + private class BlockSubheaderCell extends View implements TextSelectionHelper.ArticleSelectableView { private DrawingText textLayout; private int textX = AndroidUtilities.dp(18); @@ -11466,11 +11546,13 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - private void drawTextSelection(Canvas canvas, TextSelectionHelper.ArticleSelectableView view) { + private void drawTextSelection(Canvas canvas, TextSelectionHelper.ArticleSelectableView + view) { drawTextSelection(canvas, view, 0); } - private void drawTextSelection(Canvas canvas, TextSelectionHelper.ArticleSelectableView view, int i) { + private void drawTextSelection(Canvas canvas, TextSelectionHelper.ArticleSelectableView + view, int i) { View v = (View) view; if (v.getTag() != null && v.getTag() == BOTTOM_SHEET_VIEW_TAG && textSelectionHelperBottomSheet != null) { textSelectionHelperBottomSheet.draw(canvas, view, i); @@ -11617,6 +11699,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private final static int gallery_menu_share = 2; private final static int gallery_menu_openin = 3; private final static int gallery_menu_savegif = 4; + private final static int gallery_menu_scan = 5; private static DecelerateInterpolator decelerateInterpolator; private static Paint progressPaint; @@ -11818,7 +11901,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg parentActivity.startActivityForResult(Intent.createChooser(intent, LocaleController.getString("ShareFile", R.string.ShareFile)), 500); } else { AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setMessage(LocaleController.getString("PleaseDownload", R.string.PleaseDownload)); showDialog(builder.create()); @@ -12244,6 +12327,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (currentAnimation != null) { menuItem.setVisibility(View.VISIBLE); menuItem.hideSubItem(gallery_menu_save); + menuItem.hideSubItem(gallery_menu_scan); menuItem.showSubItem(gallery_menu_savegif); actionBar.setTitle(LocaleController.getString("AttachGif", R.string.AttachGif)); } else { @@ -12258,6 +12342,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, currentIndex + 1, imagesArr.size())); } menuItem.showSubItem(gallery_menu_save); + menuItem.showSubItem(gallery_menu_scan); menuItem.hideSubItem(gallery_menu_savegif); } groupedPhotosListView.fillList(); @@ -13175,7 +13260,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg animateTo(newScale, newTx, newTy, isZoom, 250); } - private void animateTo(float newScale, float newTx, float newTy, boolean isZoom, int duration) { + private void animateTo(float newScale, float newTx, float newTy, boolean isZoom, + int duration) { if (scale == newScale && translationX == newTx && translationY == newTy) { return; } @@ -13554,7 +13640,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return false; } - private ImageReceiver getImageReceiverView(View view, TLRPC.PageBlock pageBlock, int[] coords) { + private ImageReceiver getImageReceiverView(View view, TLRPC.PageBlock pageBlock, + int[] coords) { if (view instanceof BlockPhotoCell) { BlockPhotoCell cell = (BlockPhotoCell) view; if (cell.currentBlock == pageBlock) { @@ -13597,7 +13684,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return null; } - private ImageReceiver getImageReceiverFromListView(ViewGroup listView, TLRPC.PageBlock pageBlock, int[] coords) { + private ImageReceiver getImageReceiverFromListView(ViewGroup listView, TLRPC.PageBlock + pageBlock, int[] coords) { int count = listView.getChildCount(); for (int a = 0; a < count; a++) { ImageReceiver imageReceiver = getImageReceiverView(listView.getChildAt(a), pageBlock, coords); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java index 1d886d596..f9bd1289b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java @@ -34,6 +34,7 @@ import org.telegram.SQLite.SQLiteCursor; import org.telegram.SQLite.SQLiteDatabase; import org.telegram.SQLite.SQLitePreparedStatement; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; @@ -67,6 +68,12 @@ import org.telegram.ui.Components.UndoView; import java.io.File; import java.util.ArrayList; +import kotlin.Unit; +import tw.nekomimi.nekogram.BottomBuilder; +import tw.nekomimi.nekogram.transtale.TranslateDb; +import tw.nekomimi.nekogram.utils.EnvUtil; +import tw.nekomimi.nekogram.utils.FileUtil; + public class CacheControlActivity extends BaseFragment { private ListAdapter listAdapter; @@ -128,6 +135,10 @@ public class CacheControlActivity extends BaseFragment { Utilities.globalQueue.postRunnable(() -> { cacheSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), 0); + + cacheSize += getDirectorySize(new File(ApplicationLoader.getDataDirFixed(), "cache"), 0); + cacheSize += getDirectorySize(ApplicationLoader.applicationContext.getExternalFilesDir("logs"), 0); + if (canceled) { return; } @@ -194,12 +205,12 @@ public class CacheControlActivity extends BaseFragment { View view = layoutManager.findViewByPosition(storageUsageRow); if (view instanceof StroageUsageView) { StroageUsageView stroageUsageView = ((StroageUsageView) view); - long currentTime = System.currentTimeMillis(); + long currentTime = System.currentTimeMillis(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && currentTime - fragmentCreateTime > 250) { TransitionSet transition = new TransitionSet(); ChangeBounds changeBounds = new ChangeBounds(); changeBounds.setDuration(250); - changeBounds.excludeTarget(stroageUsageView.legendLayout,true); + changeBounds.excludeTarget(stroageUsageView.legendLayout, true); Fade in = new Fade(Fade.IN); in.setDuration(290); transition @@ -291,6 +302,31 @@ public class CacheControlActivity extends BaseFragment { if (type == FileLoader.MEDIA_DIR_CACHE) { cacheSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), documentsMusicType); imagesCleared = true; + + try { + + FileUtil.delete(new File(ApplicationLoader.getDataDirFixed(), "cache")); + + } catch (Exception ignored) { + } + + try { + + FileUtil.delete(new File(EnvUtil.getTelegramPath(), "logs")); + + } catch (Exception ignored) { + } + + try { + + // :) + + FileUtil.delete(ApplicationLoader.applicationContext.getExternalFilesDir("Telegram")); + FileUtil.delete(Environment.getExternalStoragePublicDirectory("Telegram")); + + } catch (Exception ignored) { + } + } else if (type == FileLoader.MEDIA_DIR_AUDIO) { audioSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_AUDIO), documentsMusicType); } else if (type == FileLoader.MEDIA_DIR_DOCUMENT) { @@ -504,13 +540,11 @@ public class CacheControlActivity extends BaseFragment { } private void clearDatabase() { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("LocalDatabaseClearTextTitle", R.string.LocalDatabaseClearTextTitle)); - builder.setMessage(LocaleController.getString("LocalDatabaseClearText", R.string.LocalDatabaseClearText)); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - builder.setPositiveButton(LocaleController.getString("CacheClear", R.string.CacheClear), (dialogInterface, i) -> { + BottomBuilder builder = new BottomBuilder(getParentActivity()); + builder.addTitle(LocaleController.getString("LocalDatabaseClearTextTitle", R.string.LocalDatabaseClearTextTitle), LocaleController.getString("LocalDatabaseClearText", R.string.LocalDatabaseClearText)); + builder.addItem(LocaleController.getString("CacheClear", R.string.CacheClear),R.drawable.baseline_delete_sweep_24, true, (i) -> { if (getParentActivity() == null) { - return; + return Unit.INSTANCE; } final AlertDialog progressDialog = new AlertDialog(getParentActivity(), 3); progressDialog.setCanCacnel(false); @@ -591,6 +625,9 @@ public class CacheControlActivity extends BaseFragment { database.executeFast("PRAGMA journal_size_limit = 0").stepThis().dispose(); database.executeFast("VACUUM").stepThis().dispose(); database.executeFast("PRAGMA journal_size_limit = -1").stepThis().dispose(); + + TranslateDb.clearAll(); + } catch (Exception e) { FileLog.e(e); } finally { @@ -607,13 +644,10 @@ public class CacheControlActivity extends BaseFragment { }); } }); + return Unit.INSTANCE; }); - AlertDialog alertDialog = builder.create(); - showDialog(alertDialog); - TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); - if (button != null) { - button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); - } + builder.addCancelItem(); + builder.show(); } @Override 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 2fa992241..ecaa9862e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -125,15 +125,17 @@ import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.PhotoViewer; import org.telegram.ui.SecretMediaViewer; -import tw.nekomimi.nekogram.NekoConfig; - import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.Locale; +import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.utils.AlertUtil; + public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate, ImageReceiver.ImageReceiverDelegate, DownloadController.FileDownloadProgressListener, TextSelectionHelper.SelectableView { public interface ChatMessageCellDelegate { @@ -1655,27 +1657,37 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } }); - builder.show(); + // nekox change: avoid BTE + try { + builder.show(); + } catch (Exception e) { + FileLog.e(e); + } } else { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setItems(new CharSequence[]{LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("CopyDetails", R.string.CopyDetails)}, (dialogInterface, i) -> { if (i == 0) { try { AndroidUtilities.addToClipboard(button.button.text); - Toast.makeText(getContext(), LocaleController.getString("TextCopied", R.string.TextCopied), Toast.LENGTH_SHORT).show(); + AlertUtil.showToast(LocaleController.getString("TextCopied", R.string.TextCopied)); } catch (Exception e) { FileLog.e(e); } } else if (i == 1) { try { AndroidUtilities.addToClipboard(gson.toJson(button.button)); - Toast.makeText(getContext(), LocaleController.getString("TextCopied", R.string.TextCopied), Toast.LENGTH_SHORT).show(); + AlertUtil.showToast(LocaleController.getString("TextCopied", R.string.TextCopied)); } catch (Exception e) { FileLog.e(e); } } }); - builder.show(); + // nekox change: avoid BTE + try { + builder.show(); + } catch (Exception e) { + FileLog.e(e); + } } } pressedBotButton = -1; @@ -2523,7 +2535,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } @Override - protected void onAttachedToWindow() { + public void onAttachedToWindow() { super.onAttachedToWindow(); if (messageObjectToSet != null) { @@ -2586,6 +2598,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } + private boolean lastTranslated; + private void setMessageContent(MessageObject messageObject, MessageObject.GroupedMessages groupedMessages, boolean bottomNear, boolean topNear) { if (messageObject.checkLayout() || currentPosition != null && lastHeight != AndroidUtilities.displaySize.y) { currentMessageObject = null; @@ -2641,7 +2655,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } groupChanged = newPosition != currentPosition; } - if (messageChanged || dataChanged || groupChanged || pollChanged || isPhotoDataChanged(messageObject) || pinnedBottom != bottomNear || pinnedTop != topNear) { + boolean transChanged = false; + if (lastTranslated != messageObject.messageOwner.translated) { + lastTranslated = messageObject.messageOwner.translated; + transChanged = true; + } + if (messageChanged || dataChanged || groupChanged || pollChanged || isPhotoDataChanged(messageObject) || pinnedBottom != bottomNear || pinnedTop != topNear || transChanged) { pinnedBottom = bottomNear; pinnedTop = topNear; currentMessageObject = messageObject; @@ -3859,7 +3878,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (pollVoted) { messageObject.checkedVotes.clear(); } - titleLayout = new StaticLayout(Emoji.replaceEmoji(media.poll.question, Theme.chat_audioTitlePaint.getFontMetricsInt(), AndroidUtilities.dp(16), false), Theme.chat_audioTitlePaint, maxWidth + AndroidUtilities.dp(2) - getExtraTextX() * 2, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + + String question; + + if (messageObject.messageOwner.translated) { + question = media.poll.translatedQuestion; + if (question == null) { + messageObject.messageOwner.translated = false; + question = media.poll.question; + } + } else { + question = media.poll.question; + } + + titleLayout = new StaticLayout(Emoji.replaceEmoji(question, Theme.chat_audioTitlePaint.getFontMetricsInt(), AndroidUtilities.dp(16), false), Theme.chat_audioTitlePaint, maxWidth + AndroidUtilities.dp(2) - getExtraTextX() * 2, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); boolean titleRtl = false; if (titleLayout != null) { for (int a = 0, N = titleLayout.getLineCount(); a < N; a++) { @@ -3995,7 +4027,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate for (int a = 0, N = media.poll.answers.size(); a < N; a++) { PollButton button = new PollButton(); button.answer = media.poll.answers.get(a); - button.title = new StaticLayout(Emoji.replaceEmoji(button.answer.text, Theme.chat_audioPerformerPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false), Theme.chat_audioPerformerPaint, maxWidth - AndroidUtilities.dp(33), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + + String answerText; + if (messageObject.messageOwner.translated) { + answerText = button.answer.translatedText; + } else { + answerText = button.answer.text; + } + + button.title = new StaticLayout(Emoji.replaceEmoji(answerText, Theme.chat_audioPerformerPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false), Theme.chat_audioPerformerPaint, maxWidth - AndroidUtilities.dp(33), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); button.y = height + AndroidUtilities.dp(52); button.height = button.title.getHeight(); pollButtons.add(button); @@ -8262,8 +8302,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate timeString = ""; } else if (edited) { timeString = LocaleController.getString("EditedMessage", R.string.EditedMessage) + " " + LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000); - } else { + } else if (LocaleController.getInstance().formatterDay != null && LocaleController.getInstance().formatterYear != null) { timeString = LocaleController.getInstance().formatterDay.format((long) (messageObject.messageOwner.date) * 1000); + } else { + timeString = messageObject.messageOwner.date + ""; } if (signString != null) { currentTimeString = ", " + timeString; 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 731013490..1ec506073 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java @@ -3,6 +3,7 @@ package org.telegram.ui.Cells; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; +import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; @@ -34,6 +35,7 @@ import android.widget.TextView; import androidx.recyclerview.widget.LinearLayoutManager; +import org.jetbrains.annotations.NotNull; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.Emoji; @@ -41,6 +43,7 @@ import org.telegram.messenger.MessageObject; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.ui.ActionBar.ActionBarPopupWindow; +import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.FloatingActionMode; import org.telegram.ui.ActionBar.FloatingToolbar; import org.telegram.ui.ActionBar.Theme; @@ -50,9 +53,14 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; -import tw.nekomimi.nekogram.MessageHelper; -import static com.google.zxing.common.detector.MathUtils.distance; +import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.transtale.TranslateBottomSheet; +import tw.nekomimi.nekogram.transtale.TranslateDb; +import tw.nekomimi.nekogram.transtale.Translator; +import tw.nekomimi.nekogram.utils.AlertUtil; +import tw.nekomimi.nekogram.utils.ProxyUtil; +import static com.google.zxing.common.detector.MathUtils.distance; import static org.telegram.ui.ActionBar.FloatingToolbar.STYLE_THEME; import static org.telegram.ui.ActionBar.Theme.key_chat_inTextSelectionHighlight; @@ -1216,9 +1224,9 @@ public abstract class TextSelectionHelper { + pro.show(); + Translator.translate(urlFinal, this); + }); + } + }); + } } default: clear(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 8d2a426b2..b54a1c482 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -19,6 +19,7 @@ import android.app.Activity; import android.app.DatePickerDialog; import android.app.Dialog; import android.content.ClipData; +import android.content.ClipboardManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -206,13 +207,6 @@ import org.telegram.ui.Components.URLSpanUserMention; import org.telegram.ui.Components.UndoView; import org.telegram.ui.Components.voip.VoIPHelper; -import tw.nekomimi.nekogram.MessageDetailsActivity; -import tw.nekomimi.nekogram.MessageHelper; -import tw.nekomimi.nekogram.NekoConfig; -import tw.nekomimi.nekogram.settings.NekoGeneralSettingsActivity; -import tw.nekomimi.nekogram.translator.Translator; -import tw.nekomimi.nekogram.translator.TranslateBottomSheet; - import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; @@ -226,6 +220,16 @@ import java.util.concurrent.CountDownLatch; import java.util.regex.Matcher; import java.util.regex.Pattern; +import cn.hutool.core.util.StrUtil; +import kotlin.Unit; +import tw.nekomimi.nekogram.MessageDetailsActivity; +import tw.nekomimi.nekogram.MessageHelper; +import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.NekoXConfig; +import tw.nekomimi.nekogram.parts.MessageTransKt; +import tw.nekomimi.nekogram.transtale.Translator; +import tw.nekomimi.nekogram.utils.AlertUtil; + @SuppressWarnings("unchecked") public class ChatActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate, LocationActivity.LocationActivityDelegate, ChatAttachAlertDocumentLayout.DocumentSelectActivityDelegate { @@ -245,6 +249,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not protected ChatActivityEnterView chatActivityEnterView; int chatActivityEnterViewAnimateFromTop; private View timeItem2; + private ActionBarMenuSubItem fakeScreenshotItem; private ActionBarMenuItem attachItem; private ActionBarMenuItem headerItem; private ActionBarMenuItem editTextItem; @@ -252,11 +257,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private RadialProgressView progressBar; private ActionBarMenuSubItem addContactItem; private ClippingImageView animatingImageView; - private RecyclerListView chatListView; + public RecyclerListView chatListView; private ChatListItemAnimator chatListItemAniamtor; private int chatListViewClipTop; private GridLayoutManagerFixed chatLayoutManager; - private ChatActivityAdapter chatAdapter; + public ChatActivityAdapter chatAdapter; private UnreadCounterTextView bottomOverlayChatText; private UnreadCounterTextView bottomOverlayChatText2; private RadialProgressView bottomOverlayProgress; @@ -641,7 +646,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not replaceAnimator.cancel(); } replaceProgress = 0; - replaceAnimator = ValueAnimator.ofFloat(0,1f); + replaceAnimator = ValueAnimator.ofFloat(0, 1f); replaceAnimator.addUpdateListener(animation -> { replaceProgress = (float) animation.getAnimatedValue(); invalidate(); @@ -651,6 +656,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + public void setText(CharSequence text) { layoutTextWidth = (int) Math.ceil(layoutPaint.measureText(text, 0, text.length())); textLayout = new StaticLayout(text, layoutPaint, layoutTextWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true); @@ -928,6 +934,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int edit = 23; private final static int add_shortcut = 24; private final static int show_pinned = 25; + private final static int translate = 101; + + private final static int fake_screenshot = 27; + private final static int delete_all = 28; private final static int bot_help = 30; private final static int bot_settings = 31; @@ -945,9 +955,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int text_strike = 55; private final static int text_underline = 56; private final static int text_mention = 57; + private final static int text_transalte = 58; private final static int search = 40; + private final static int linked_chat = 60; + private final static int id_chat_compose_panel = 1000; RecyclerListView.OnItemLongClickListenerExtended onItemLongClickListener = new RecyclerListView.OnItemLongClickListenerExtended() { @@ -1403,6 +1416,35 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + private ArrayList getSelectedMessages() { + + ArrayList fmessages = new ArrayList<>(); + + for (int a = 1; a >= 0; a--) { + ArrayList ids = new ArrayList<>(); + for (int b = 0; b < selectedMessagesIds[a].size(); b++) { + ids.add(selectedMessagesIds[a].keyAt(b)); + } + Collections.sort(ids); + for (int b = 0; b < ids.size(); b++) { + Integer id = ids.get(b); + MessageObject messageObject = selectedMessagesIds[a].get(id); + if (messageObject != null) { + fmessages.add(messageObject); + } + } + selectedMessagesCanCopyIds[a].clear(); + selectedMessagesCanStarIds[a].clear(); + selectedMessagesIds[a].clear(); + } + hideActionMode(); + updatePinnedMessageView(true); + updateVisibleRows(); + + return fmessages; + + } + @Override public View createView(Context context) { textSelectionHelper = new TextSelectionHelper.ChatListTextSelectionHelper(); @@ -1488,6 +1530,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AndroidUtilities.addToClipboard(str); } clearSelectionMode(); + } else if (id == translate) { + MessageTransKt.translateMessages(ChatActivity.this, getSelectedMessages().toArray(new MessageObject[0])); } else if (id == delete) { if (getParentActivity() == null) { return; @@ -1501,7 +1545,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } showDialog(AlertsCreator.createTTLAlert(getParentActivity(), currentEncryptedChat).create()); - } else if (id == delete_history) { + } else if (id == delete_history || id == delete_all) { AlertDialog.Builder builder = new AlertDialog.Builder(context); TextView messageTextView = new TextView(context); messageTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); @@ -1525,17 +1569,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not textView.setSingleLine(true); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); textView.setEllipsize(TextUtils.TruncateAt.END); - textView.setText(LocaleController.getString("DeleteAllFromSelf", R.string.DeleteAllFromSelf)); + if (id == delete_history) { + textView.setText(LocaleController.getString("DeleteAllFromSelf", R.string.DeleteAllFromSelf)); + } else { + textView.setText(LocaleController.getString("DeleteAllInChat", R.string.DeleteAllInChat)); + } frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 21 : 76), 11, (LocaleController.isRTL ? 76 : 21), 0)); frameLayout.addView(messageTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 57, 24, 9)); - messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllFromSelfAlert", R.string.DeleteAllFromSelfAlert))); - builder.setPositiveButton(LocaleController.getString("DeleteAll", R.string.DeleteAll), (dialogInterface, i) -> { - if (ChatObject.canUserDoAction(currentChat, ChatObject.ACTION_DELETE_MESSAGES)) { - getMessagesController().deleteUserChannelHistory(currentChat, UserConfig.getInstance(currentAccount).getCurrentUser(), 0); - } else { - MessageHelper.getInstance(currentAccount).deleteUserChannelHistoryWithSearch(dialog_id, UserConfig.getInstance(currentAccount).getCurrentUser()); - } - }); + if (id == delete_history) { + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllFromSelfAlert", R.string.DeleteAllFromSelfAlert))); + builder.setPositiveButton(LocaleController.getString("DeleteAll", R.string.DeleteAll), (dialogInterface, i) -> { + if (ChatObject.canUserDoAction(currentChat, ChatObject.ACTION_DELETE_MESSAGES)) { + getMessagesController().deleteUserChannelHistory(currentChat, UserConfig.getInstance(currentAccount).getCurrentUser(), 0); + } else { + MessageHelper.getInstance(currentAccount).deleteUserChannelHistoryWithSearch(dialog_id, UserConfig.getInstance(currentAccount).getCurrentUser()); + } + }); + } else { + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllInChatAlert", R.string.DeleteAllInChatAlert))); + builder.setPositiveButton(LocaleController.getString("DeleteAllInChat", R.string.DeleteAllInChat), (dialogInterface, i) -> { + MessageHelper.getInstance(currentAccount).deleteChannelHistory(dialog_id, currentChat, 0); + }); + } + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); AlertDialog alertDialog = builder.create(); showDialog(alertDialog); @@ -1564,11 +1620,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (id == clear_history) { if (chatInfo != null && chatInfo.pinned_msg_id != 0) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - preferences.edit().putInt("pin_" + dialog_id, chatInfo.pinned_msg_id).commit(); + preferences.edit().putInt("pin_" + dialog_id, chatInfo.pinned_msg_id).apply(); updatePinnedMessageView(true); } else if (userInfo != null && userInfo.pinned_msg_id != 0) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - preferences.edit().putInt("pin_" + dialog_id, userInfo.pinned_msg_id).commit(); + preferences.edit().putInt("pin_" + dialog_id, userInfo.pinned_msg_id).apply(); updatePinnedMessageView(true); } getMessagesController().deleteDialog(dialog_id, 1, param); @@ -1698,10 +1754,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedRegular(); } + } else if (id == text_transalte) { + if (chatActivityEnterView != null) { + chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); + chatActivityEnterView.getEditField().makeSelectedTranslate(); + } } else if (id == show_pinned) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - preferences.edit().putInt("pin_" + dialog_id, 0).commit(); + preferences.edit().putInt("pin_" + dialog_id, 0).apply(); updatePinnedMessageView(true); + } else if (id == fake_screenshot) { + getSecretChatHelper().sendScreenshotMessage(currentEncryptedChat, getMediaController().getLastVisibleMessageIds(), null); + } else if (id == linked_chat) { + if (chatInfo == null) { + return; + } + Bundle args = new Bundle(); + args.putInt("chat_id", chatInfo.linked_chat_id); + if (!getMessagesController().checkCanOpenChat(args, ChatActivity.this)) { + return; + } + presentFragment(new ChatActivity(args)); } } }); @@ -1854,7 +1927,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not headerItem = menu.addItem(0, R.drawable.ic_ab_other); headerItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); if (currentUser != null) { - headerItem.addSubItem(call, R.drawable.msg_callback, LocaleController.getString("Call", R.string.Call)); + headerItem.addSubItem(call, R.drawable.baseline_call_24, LocaleController.getString("Call", R.string.Call)); TLRPC.UserFull userFull = getMessagesController().getUserFull(currentUser.id); if (userFull != null && userFull.phone_calls_available) { headerItem.showSubItem(call); @@ -1867,6 +1940,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not editTextItem.setTag(null); editTextItem.setVisibility(View.GONE); + editTextItem.addSubItem(text_transalte, LocaleController.getString("Translate", R.string.Translate)); + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(LocaleController.getString("Bold", R.string.Bold)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); editTextItem.addSubItem(text_bold, stringBuilder); @@ -1893,13 +1968,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not editTextItem.addSubItem(text_regular, LocaleController.getString("Regular", R.string.Regular)); if (searchItem != null) { - headerItem.addSubItem(search, R.drawable.msg_search, LocaleController.getString("Search", R.string.Search)); + headerItem.addSubItem(search, R.drawable.baseline_search_24, LocaleController.getString("Search", R.string.Search)); } if (currentUser != null) { - addContactItem = headerItem.addSubItem(share_contact, R.drawable.msg_addcontact, ""); + addContactItem = headerItem.addSubItem(share_contact, R.drawable.baseline_person_add_24, ""); } if (currentEncryptedChat != null) { - timeItem2 = headerItem.addSubItem(chat_enc_timer, R.drawable.msg_timer, LocaleController.getString("SetTimer", R.string.SetTimer)); + timeItem2 = headerItem.addSubItem(chat_enc_timer, R.drawable.baseline_timer_24, LocaleController.getString("SetTimer", R.string.SetTimer)); + fakeScreenshotItem = headerItem.addSubItem(fake_screenshot, R.drawable.baseline_star_24, LocaleController.getString("FakeScreenshot", R.string.FakeScreenshot)); } boolean allowShowPinned; @@ -1913,44 +1989,59 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not allowShowPinned = false; } if (allowShowPinned) { - headerItem.addSubItem(show_pinned, R.drawable.msg_pin, LocaleController.getString("PinnedMessage", R.string.PinnedMessage)); + headerItem.addSubItem(show_pinned, R.drawable.deproko_baseline_pin_24, LocaleController.getString("PinnedMessage", R.string.PinnedMessage)); } if (currentUser == null || !currentUser.self) { - muteItem = headerItem.addSubItem(mute, R.drawable.msg_mute, null); + muteItem = headerItem.addSubItem(mute, R.drawable.baseline_volume_off_24_white, null); } if (currentChat != null && !currentChat.creator) { - headerItem.addSubItem(report, R.drawable.msg_report, LocaleController.getString("ReportChat", R.string.ReportChat)); + headerItem.addSubItem(report, R.drawable.baseline_report_24, LocaleController.getString("ReportChat", R.string.ReportChat)); } + + if (currentChat != null && (currentChat.has_link || (chatInfo != null && chatInfo.linked_chat_id != 0))) { + String text; + if (!currentChat.megagroup) { + text = LocaleController.getString("LinkedGroupChat", R.string.LinkedGroupChat); + } else { + text = LocaleController.getString("LinkedChannelChat", R.string.LinkedChannelChat); + } + headerItem.addSubItem(linked_chat, R.drawable.baseline_layers_24, text); + } + if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup && TextUtils.isEmpty(currentChat.username)) { - headerItem.addSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory)); + headerItem.addSubItem(clear_history, R.drawable.baseline_delete_sweep_24, LocaleController.getString("ClearHistory", R.string.ClearHistory)); } if (ChatObject.isChannel(currentChat) && currentChat.megagroup) { - headerItem.addSubItem(delete_history, R.drawable.msg_delete, LocaleController.getString("DeleteAllFromSelf", R.string.DeleteAllFromSelf)); + headerItem.addSubItem(delete_history, R.drawable.baseline_delete_24, LocaleController.getString("DeleteAllFromSelf", R.string.DeleteAllFromSelf)); + } + + if (ChatObject.isChannel(currentChat) && ChatObject.canUserDoAction(currentChat, ChatObject.ACTION_DELETE_MESSAGES)) { + headerItem.addSubItem(delete_all, R.drawable.baseline_delete_24, LocaleController.getString("DeleteAllInChat", R.string.DeleteAllInChat)); } if (ChatObject.isChannel(currentChat)) { if (!ChatObject.isNotInChat(currentChat)) { if (currentChat.megagroup) { - headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("LeaveMegaMenu", R.string.LeaveMegaMenu)); + headerItem.addSubItem(delete_chat, R.drawable.baseline_exit_to_app_24, LocaleController.getString("LeaveMegaMenu", R.string.LeaveMegaMenu)); } else { - headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu)); + headerItem.addSubItem(delete_chat, R.drawable.baseline_exit_to_app_24, LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu)); } } } else if (!ChatObject.isChannel(currentChat)) { if (currentChat != null) { - headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); + headerItem.addSubItem(delete_chat, R.drawable.baseline_exit_to_app_24, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); } else { - headerItem.addSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser)); + headerItem.addSubItem(delete_chat, R.drawable.baseline_delete_24, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser)); } } if (currentUser != null && currentUser.self) { - headerItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); + headerItem.addSubItem(add_shortcut, R.drawable.baseline_home_24, LocaleController.getString("AddShortcut", R.string.AddShortcut)); } if (currentUser != null && currentEncryptedChat == null && currentUser.bot) { - headerItem.addSubItem(bot_settings, R.drawable.menu_settings, LocaleController.getString("BotSettings", R.string.BotSettings)); - headerItem.addSubItem(bot_help, R.drawable.menu_help, LocaleController.getString("BotHelp", R.string.BotHelp)); + headerItem.addSubItem(bot_settings, R.drawable.baseline_settings_24, LocaleController.getString("BotSettings", R.string.BotSettings)); + headerItem.addSubItem(bot_help, R.drawable.baseline_help_24, LocaleController.getString("BotHelp", R.string.BotHelp)); updateBotButtons(); } } @@ -1981,22 +2072,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); + actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.baseline_edit_24, AndroidUtilities.dp(54), LocaleController.getString("Edit", R.string.Edit))); + actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.baseline_favorite_20, AndroidUtilities.dp(54), LocaleController.getString("AddToFavorites", R.string.AddToFavorites))); + actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.baseline_content_copy_24, AndroidUtilities.dp(54), LocaleController.getString("Copy", R.string.Copy))); + if (currentEncryptedChat == null) { - actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString("Edit", R.string.Edit))); - actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString("AddToFavorites", R.string.AddToFavorites))); - actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString("Copy", R.string.Copy))); - actionModeViews.add(actionMode.addItemWithWidth(forward_noquote, R.drawable.msg_forward_noquote, AndroidUtilities.dp(54), LocaleController.getString("NoQuoteForward", R.string.NoQuoteForward))); actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward))); - actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); - } else { - actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString("Edit", R.string.Edit))); - actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString("AddToFavorites", R.string.AddToFavorites))); - actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString("Copy", R.string.Copy))); - actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); + actionModeViews.add(actionMode.addItemWithWidth(forward_noquote, R.drawable.msg_forward_noquote, AndroidUtilities.dp(54), LocaleController.getString("NoQuoteForward", R.string.NoQuoteForward))); } + + actionModeViews.add(actionMode.addItemWithWidth(translate, R.drawable.ic_translate, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Translate))); + actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.baseline_delete_24, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); + actionMode.getItem(edit).setVisibility(canEditMessagesCount == 1 && selectedMessagesIds[0].size() + selectedMessagesIds[1].size() == 1 ? View.VISIBLE : View.GONE); actionMode.getItem(copy).setVisibility(selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); actionMode.getItem(star).setVisibility(selectedMessagesCanStarIds[0].size() + selectedMessagesCanStarIds[1].size() != 0 ? View.VISIBLE : View.GONE); + actionMode.getItem(translate).setVisibility(canEditMessagesCount == 1 && selectedMessagesIds[0].size() + selectedMessagesIds[1].size() == 1 ? View.GONE : View.VISIBLE); actionMode.getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); checkActionBarMenu(); @@ -2071,7 +2162,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (scrimView != null && (child == pagedownButton || child == mentiondownButton || child == floatingDateView || child == fireworksOverlay)) { return false; } - if (getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND) != null ) { + if (getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND) != null) { boolean needBlur; if (((int) getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND)) == BlurBehindDrawable.STATIC_CONTENT) { needBlur = child == actionBar; @@ -2081,7 +2172,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!needBlur) { return false; } - } else if (getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND) == null && instantCameraView.blurFullyDrawing()) { + } else if (getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND) == null && instantCameraView.blurFullyDrawing()) { boolean needBlur = child == actionBar || child == chatListView || child == pinnedMessageView || child == fragmentContextView; if (needBlur) { return false; @@ -2337,7 +2428,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not heightSize -= actionBarHeight; } - if (lastHeight != allHeight && ! SharedConfig.smoothKeyboard) { + if (lastHeight != allHeight && !SharedConfig.smoothKeyboard) { measureKeyboardHeight(); } int keyboardSize = SharedConfig.smoothKeyboard ? 0 : getKeyboardHeight(); @@ -3364,7 +3455,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ); } canvas.translate(canvasOffsetX, canvasOffsetY); - cell.drawCaptionLayout(canvas, selectionOnly, alpha); + cell.drawCaptionLayout(canvas, selectionOnly, alpha); canvas.restore(); } drawCaptionAfter.clear(); @@ -3497,13 +3588,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not nextPosition = p - 1; } if (chatMessageCell.willRemovedAfterAnimation()) { - View view = chatScrollHelper.positionToOldView.get(nextPosition); - if (view != null) { - if (child.getTranslationY() != 0) { - canvas.restore(); - } - return result; - } + View view = chatScrollHelper.positionToOldView.get(nextPosition); + if (view != null) { + if (child.getTranslationY() != 0) { + canvas.restore(); + } + return result; + } } else { ViewHolder holder = chatListView.findViewHolderForAdapterPosition(nextPosition); if (holder != null) { @@ -4002,7 +4093,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pinnedMessageView.setTranslationY(-AndroidUtilities.dp(50)); pinnedMessageView.setVisibility(View.GONE); pinnedMessageView.setBackgroundResource(R.drawable.blockpanel); - pinnedMessageView.getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); + pinnedMessageView.getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.SRC_IN)); contentView.addView(pinnedMessageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); pinnedMessageView.setOnClickListener(v -> { wasManualScroll = true; @@ -4033,7 +4124,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not closePinned = new ImageView(context); closePinned.setImageResource(R.drawable.miniplayer_close); - closePinned.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); + closePinned.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.SRC_IN)); closePinned.setScaleType(ImageView.ScaleType.CENTER); closePinned.setContentDescription(LocaleController.getString("Close", R.string.Close)); pinnedMessageView.addView(closePinned, LayoutHelper.createFrame(36, 48, Gravity.RIGHT | Gravity.TOP)); @@ -4059,12 +4150,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.setMessage(LocaleController.getString("UnpinMessageAlert", R.string.UnpinMessageAlert)); builder.setPositiveButton(LocaleController.getString("UnpinMessage", R.string.UnpinMessage), (dialogInterface, i) -> getMessagesController().pinMessage(currentChat, currentUser, 0, false)); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - builder.setNeutralButton(LocaleController.getString("Hide", R.string.Hide),(dialogInterface, i) -> { + builder.setNeutralButton(LocaleController.getString("Hide", R.string.Hide), (dialogInterface, i) -> { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); if (chatInfo != null) { - preferences.edit().putInt("pin_" + dialog_id, chatInfo.pinned_msg_id).commit(); + preferences.edit().putInt("pin_" + dialog_id, chatInfo.pinned_msg_id).apply(); } else if (userInfo != null) { - preferences.edit().putInt("pin_" + dialog_id, userInfo.pinned_msg_id).commit(); + preferences.edit().putInt("pin_" + dialog_id, userInfo.pinned_msg_id).apply(); } updatePinnedMessageView(true); }); @@ -4072,9 +4163,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); if (chatInfo != null) { - preferences.edit().putInt("pin_" + dialog_id, chatInfo.pinned_msg_id).commit(); + preferences.edit().putInt("pin_" + dialog_id, chatInfo.pinned_msg_id).apply(); } else if (userInfo != null) { - preferences.edit().putInt("pin_" + dialog_id, userInfo.pinned_msg_id).commit(); + preferences.edit().putInt("pin_" + dialog_id, userInfo.pinned_msg_id).apply(); } updatePinnedMessageView(true); } @@ -4129,7 +4220,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not topChatPanelView.setTranslationY(-AndroidUtilities.dp(50)); topChatPanelView.setVisibility(View.GONE); topChatPanelView.setBackgroundResource(R.drawable.blockpanel); - topChatPanelView.getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); + topChatPanelView.getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.SRC_IN)); contentView.addView(topChatPanelView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); reportSpamButton = new TextView(context); @@ -4174,7 +4265,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not closeReportSpam = new ImageView(context); closeReportSpam.setImageResource(R.drawable.miniplayer_close); - closeReportSpam.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); + closeReportSpam.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.SRC_IN)); closeReportSpam.setScaleType(ImageView.ScaleType.CENTER); topChatPanelView.addView(closeReportSpam, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP)); closeReportSpam.setOnClickListener(v -> { @@ -4187,7 +4278,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not alertView.setTranslationY(-AndroidUtilities.dp(50)); alertView.setVisibility(View.GONE); alertView.setBackgroundResource(R.drawable.blockpanel); - alertView.getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); + alertView.getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.SRC_IN)); contentView.addView(alertView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); alertNameTextView = new TextView(context); @@ -4559,11 +4650,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not SharedPreferences preferences = MessagesController.getGlobalMainSettings(); if (!preferences.getBoolean("secretbot", false)) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setMessage(LocaleController.getString("SecretChatContextBotAlert", R.string.SecretChatContextBotAlert)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); showDialog(builder.create()); - preferences.edit().putBoolean("secretbot", true).commit(); + preferences.edit().putBoolean("secretbot", true).apply(); } } mentionContainer.setVisibility(View.VISIBLE); @@ -4703,7 +4794,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.replaceWithText(start, len, "@" + user.username + " ", false); } else { String name = UserObject.getFirstName(user, false); - Spannable spannable = new SpannableString(name + " "); + Spannable spannable = new SpannableString("@" + name + " "); spannable.setSpan(new URLSpanUserMention("" + user.id, 3), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); chatActivityEnterView.replaceWithText(start, len, spannable, false); } @@ -4772,7 +4863,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return false; } else { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setMessage(LocaleController.getString("ClearSearch", R.string.ClearSearch)); builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> mentionsAdapter.clearRecentHashtags()); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -4783,7 +4874,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not TLRPC.User user = (TLRPC.User) object; if (!(searchingForUser && searchContainer.getVisibility() == View.VISIBLE) && user != null) { String name = UserObject.getFirstName(user, false); - Spannable spannable = new SpannableString(name + " "); + Spannable spannable = new SpannableString("@" + name + " "); spannable.setSpan(new URLSpanUserMention("" + user.id, 3), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); chatActivityEnterView.replaceWithText(start, len, spannable, false); return true; @@ -4818,7 +4909,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pagedownButtonImage = new ImageView(context); pagedownButtonImage.setImageResource(R.drawable.pagedown); pagedownButtonImage.setScaleType(ImageView.ScaleType.CENTER); - pagedownButtonImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.MULTIPLY)); + pagedownButtonImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.SRC_IN)); pagedownButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); Drawable drawable; if (Build.VERSION.SDK_INT >= 21) { @@ -4833,7 +4924,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), Theme.getColor(Theme.key_chat_goDownButton)); } Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); - shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_goDownButtonShadow), PorterDuff.Mode.MULTIPLY)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_goDownButtonShadow), PorterDuff.Mode.SRC_IN)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); drawable = combinedDrawable; @@ -4856,7 +4947,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentiondownButtonImage = new ImageView(context); mentiondownButtonImage.setImageResource(R.drawable.mentionbutton); mentiondownButtonImage.setScaleType(ImageView.ScaleType.CENTER); - mentiondownButtonImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.MULTIPLY)); + mentiondownButtonImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.SRC_IN)); mentiondownButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); if (Build.VERSION.SDK_INT >= 21) { pagedownButtonImage.setOutlineProvider(new ViewOutlineProvider() { @@ -4870,7 +4961,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), Theme.getColor(Theme.key_chat_goDownButton)); } shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); - shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_goDownButtonShadow), PorterDuff.Mode.MULTIPLY)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_goDownButtonShadow), PorterDuff.Mode.SRC_IN)); combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); drawable = combinedDrawable; @@ -5452,12 +5543,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); replyIconImageView = new ImageView(context); - replyIconImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_replyPanelIcons), PorterDuff.Mode.MULTIPLY)); + replyIconImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_replyPanelIcons), PorterDuff.Mode.SRC_IN)); replyIconImageView.setScaleType(ImageView.ScaleType.CENTER); replyLayout.addView(replyIconImageView, LayoutHelper.createFrame(52, 46, Gravity.TOP | Gravity.LEFT)); replyCloseImageView = new ImageView(context); - replyCloseImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_replyPanelClose), PorterDuff.Mode.MULTIPLY)); + replyCloseImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_replyPanelClose), PorterDuff.Mode.SRC_IN)); replyCloseImageView.setImageResource(R.drawable.input_clear); replyCloseImageView.setScaleType(ImageView.ScaleType.CENTER); replyLayout.addView(replyCloseImageView, LayoutHelper.createFrame(52, 46, Gravity.RIGHT | Gravity.TOP, 0, 0.5f, 0, 0)); @@ -5545,7 +5636,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stickersPanelArrow = new ImageView(context); stickersPanelArrow.setImageResource(R.drawable.stickers_back_arrow); - stickersPanelArrow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_stickersHintPanel), PorterDuff.Mode.MULTIPLY)); + stickersPanelArrow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_stickersHintPanel), PorterDuff.Mode.SRC_IN)); stickersPanel.addView(stickersPanelArrow, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 53, 0, 53, 0)); searchContainer = new FrameLayout(context) { @@ -5584,7 +5675,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchUpButton = new ImageView(context); searchUpButton.setScaleType(ImageView.ScaleType.CENTER); searchUpButton.setImageResource(R.drawable.msg_go_up); - searchUpButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); + searchUpButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.SRC_IN)); searchUpButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchUpButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 48, 0)); searchUpButton.setOnClickListener(view -> { @@ -5604,7 +5695,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchDownButton = new ImageView(context); searchDownButton.setScaleType(ImageView.ScaleType.CENTER); searchDownButton.setImageResource(R.drawable.msg_go_down); - searchDownButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); + searchDownButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.SRC_IN)); searchDownButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchDownButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 0, 0)); searchDownButton.setOnClickListener(view -> { @@ -5620,7 +5711,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchUserButton = new ImageView(context); searchUserButton.setScaleType(ImageView.ScaleType.CENTER); searchUserButton.setImageResource(R.drawable.msg_usersearch); - searchUserButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); + searchUserButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.SRC_IN)); searchUserButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchUserButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP, 48, 0, 0, 0)); searchUserButton.setOnClickListener(view -> { @@ -5640,8 +5731,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchCalendarButton = new ImageView(context); searchCalendarButton.setScaleType(ImageView.ScaleType.CENTER); - searchCalendarButton.setImageResource(R.drawable.msg_calendar); - searchCalendarButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); + searchCalendarButton.setImageResource(R.drawable.baseline_date_range_24); + searchCalendarButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.SRC_IN)); searchCalendarButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchCalendarButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); searchCalendarButton.setOnClickListener(view -> { @@ -5770,7 +5861,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setMessage(LocaleController.getString("AreYouSureUnblockContact", R.string.AreYouSureUnblockContact)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> getMessagesController().unblockUser(currentUser.id)); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } @@ -5791,7 +5882,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (hasReportSpam() && reportSpamButton.getTag(R.id.object_tag) != null) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - preferences.edit().putInt("dialog_bar_vis3" + dialog_id, 3).commit(); + preferences.edit().putInt("dialog_bar_vis3" + dialog_id, 3).apply(); getNotificationCenter().postNotificationName(NotificationCenter.peerSettingsDidLoad, dialog_id); } } else { @@ -5810,7 +5901,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not bottomOverlayChatText2 = new UnreadCounterTextView(context); bottomOverlayChatText2.setVisibility(View.GONE); - bottomOverlayChat.addView(bottomOverlayChatText2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 1.5f, 0, 0)); + bottomOverlayChat.addView(bottomOverlayChatText2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 1.5f, 0, 0)); bottomOverlayChatText2.setOnClickListener(v -> { if (chatInfo == null) { return; @@ -5832,17 +5923,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not bottomOverlayProgress.setAlpha(1.0f); bottomOverlayChat.addView(bottomOverlayProgress, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); + Theme.ThemeInfo currentTheme = Theme.getCurrentTheme(); + + boolean isMaterial = currentTheme.assetName != null && currentTheme.assetName.startsWith("nekox-indigo"); + replyButton = new TextView(context); replyButton.setText(LocaleController.getString("Reply", R.string.Reply)); replyButton.setGravity(Gravity.CENTER_VERTICAL); replyButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); replyButton.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(21), 0); replyButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 3)); - replyButton.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon)); + replyButton.setTextColor(Theme.getColor(isMaterial ? Theme.key_actionBarActionModeDefault : Theme.key_actionBarActionModeDefaultIcon)); replyButton.setCompoundDrawablePadding(AndroidUtilities.dp(7)); replyButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); Drawable image = context.getResources().getDrawable(R.drawable.input_reply).mutate(); - image.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); + image.setColorFilter(new PorterDuffColorFilter(Theme.getColor(isMaterial ? Theme.key_actionBarActionModeDefault : Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.SRC_IN)); replyButton.setCompoundDrawablesWithIntrinsicBounds(image, null, null, null); replyButton.setOnClickListener(v -> { MessageObject messageObject = null; @@ -5870,10 +5965,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not forwardButton.setPadding(AndroidUtilities.dp(21), 0, AndroidUtilities.dp(21), 0); forwardButton.setCompoundDrawablePadding(AndroidUtilities.dp(6)); forwardButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 3)); - forwardButton.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon)); + forwardButton.setTextColor(Theme.getColor(isMaterial ? Theme.key_actionBarActionModeDefault : Theme.key_actionBarActionModeDefaultIcon)); forwardButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); image = context.getResources().getDrawable(R.drawable.input_forward).mutate(); - image.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); + image.setColorFilter(new PorterDuffColorFilter(Theme.getColor(isMaterial ? Theme.key_actionBarActionModeDefault : Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.SRC_IN)); forwardButton.setCompoundDrawablesWithIntrinsicBounds(image, null, null, null); forwardButton.setOnClickListener(v -> { noForwardQuote = false; @@ -5914,7 +6009,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatScrollHelper.setAnimationCallback(chatScrollHelperCallback); try { - if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 23 && (SharedConfig.passcodeHash.length() == 0 || SharedConfig.allowScreenCapture)) { + if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 23 && (SharedConfig.passcodeHash.length() == 0 || SharedConfig.allowScreenCapture) && !NekoXConfig.disableFlagSecure) { AndroidUtilities.setFlagSecure(this, true); } } catch (Throwable e) { @@ -6349,7 +6444,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatAttachAlert.isShowing()) { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); if (chatActivityEnterView.getVisibility() == View.VISIBLE && fragmentView != null) { - // fragmentView.requestLayout(); + // fragmentView.requestLayout(); } } super.dismissInternal(); @@ -7059,7 +7154,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (preferences.getBoolean("gifhint", false)) { return; } - preferences.edit().putBoolean("gifhint", true).commit(); + preferences.edit().putBoolean("gifhint", true).apply(); if (getParentActivity() == null || fragmentView == null || gifHintTextView != null) { return; @@ -7722,10 +7817,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentEncryptedChat != null && messagesController.secretWebpagePreview == 2) { AndroidUtilities.runOnUIThread(() -> { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { messagesController.secretWebpagePreview = 1; - MessagesController.getGlobalMainSettings().edit().putInt("secretWebpage2", getMessagesController().secretWebpagePreview).commit(); + MessagesController.getGlobalMainSettings().edit().putInt("secretWebpage2", getMessagesController().secretWebpagePreview).apply(); foundUrls = null; searchLinks(charSequence, force); }); @@ -7734,7 +7829,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showDialog(builder.create()); messagesController.secretWebpagePreview = 0; - MessagesController.getGlobalMainSettings().edit().putInt("secretWebpage2", messagesController.secretWebpagePreview).commit(); + MessagesController.getGlobalMainSettings().edit().putInt("secretWebpage2", messagesController.secretWebpagePreview).apply(); }); return; } @@ -7789,7 +7884,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not waitingForSendingMessageLoad = true; } if (!fromMyName) { - AlertsCreator.showSendMediaAlert(getSendMessagesHelper().sendMessage(arrayList, did == 0 ? dialog_id : did, notify, scheduleDate), this); + AlertsCreator.showSendMediaAlert(getSendMessagesHelper().sendMessage(arrayList, did == 0 ? dialog_id : did, notify, scheduleDate), this); } else { for (MessageObject object : arrayList) { getSendMessagesHelper().processForwardFromMyName(object, did == 0 ? dialog_id : did, true, notify, scheduleDate); @@ -8087,7 +8182,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } else { - replyIconImageView.setImageResource(R.drawable.msg_link); + replyIconImageView.setImageResource(R.drawable.baseline_link_24); if (webPage instanceof TLRPC.TL_webPagePending) { replyNameTextView.setText(LocaleController.getString("GettingLinkInfo", R.string.GettingLinkInfo)); replyObjectTextView.setText(pendingLinkSearchString); @@ -8179,7 +8274,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (replyingMessageObject != null && replyingMessageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyKeyboardForceReply) { SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); - preferences.edit().putInt("answered_" + dialog_id, replyingMessageObject.getId()).commit(); + preferences.edit().putInt("answered_" + dialog_id, replyingMessageObject.getId()).apply(); } if (foundWebPage != null) { foundWebPage = null; @@ -8402,7 +8497,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int maxNegativeUnreadId = Integer.MAX_VALUE; int maxUnreadDate = Integer.MIN_VALUE; int lastVisibleId = currentEncryptedChat != null ? Integer.MAX_VALUE : Integer.MIN_VALUE; - int recyclerChatViewHeight = contentView.getHeightWithKeyboard() - (inPreviewMode ? 0 : AndroidUtilities.dp(48)) - chatListView.getTop(); + int recyclerChatViewHeight = contentView.getHeightWithKeyboard() - (inPreviewMode ? 0 : AndroidUtilities.dp(48)) - chatListView.getTop(); pollsToCheck.clear(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); @@ -8633,7 +8728,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not editor.putInt("notify2_" + dialog_id, 2); flags = 1; getMessagesStorage().setDialogFlags(dialog_id, flags); - editor.commit(); + editor.apply(); TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialog_id); if (dialog != null) { dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); @@ -8649,7 +8744,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not SharedPreferences.Editor editor = preferences.edit(); editor.putInt("notify2_" + dialog_id, 0); getMessagesStorage().setDialogFlags(dialog_id, 0); - editor.commit(); + editor.apply(); TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialog_id); if (dialog != null) { dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); @@ -9108,7 +9203,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (grantResults != null && grantResults.length != 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setMessage(LocaleController.getString("PermissionNoAudioVideo", R.string.PermissionNoAudioVideo)); builder.setNegativeButton(LocaleController.getString("PermissionOpenSettings", R.string.PermissionOpenSettings), (dialog, which) -> { try { @@ -9223,6 +9318,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return 10; } else if (mime.endsWith("/xml")) { return 5; + } else if ((messageObject.getDocumentName().toLowerCase().endsWith(".nekox.json"))) { + return 21; + } else if ((messageObject.getDocumentName().toLowerCase().endsWith(".nekox-stickers.json"))) { + return 22; } else if (!messageObject.isNewGif() && mime.endsWith("/mp4") || mime.endsWith("/png") || mime.endsWith("/jpg") || mime.endsWith("/jpeg")) { return 6; } @@ -9288,8 +9387,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mime != null && mime.endsWith("text/xml")) { return 5; } + if (mime != null && mime.endsWith("/json")) { + return 21; + } } - if (NekoConfig.shouldNOTTrustMe || messageObject.messageOwner.ttl <= 0) { + if (NekoXConfig.disableFlagSecure || messageObject.messageOwner.ttl <= 0) { return 4; } } @@ -9453,7 +9555,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } } - starItem.setIcon(hasUnfavedSelected ? R.drawable.msg_fave : R.drawable.msg_unfave); + starItem.setIcon(hasUnfavedSelected ? R.drawable.baseline_star_24 : R.drawable.baseline_star_24); final int newEditVisibility = canEditMessagesCount == 1 && selectedCount == 1 ? View.VISIBLE : View.GONE; if (replyButton != null) { boolean allowChatActions = true; @@ -9675,9 +9777,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not avatarContainer.setTitleIcons(currentEncryptedChat != null ? Theme.chat_lockIconDrawable : null, rightIcon); if (muteItem != null) { if (rightIcon != null) { - muteItem.setTextAndIcon(LocaleController.getString("UnmuteNotifications", R.string.UnmuteNotifications), R.drawable.msg_unmute); + muteItem.setTextAndIcon(LocaleController.getString("UnmuteNotifications", R.string.UnmuteNotifications), R.drawable.baseline_bullhorn_24); } else { - muteItem.setTextAndIcon(LocaleController.getString("MuteNotifications", R.string.MuteNotifications), R.drawable.msg_mute); + muteItem.setTextAndIcon(LocaleController.getString("MuteNotifications", R.string.MuteNotifications), R.drawable.baseline_volume_off_24_white); } } } @@ -10745,7 +10847,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL && getParentActivity() != null) { if (AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 17 && currentEncryptedChat.ttl > 0 && currentEncryptedChat.ttl <= 60) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setMessage(LocaleController.formatString("CompatibilityChat", R.string.CompatibilityChat, currentUser.first_name, currentUser.first_name)); showDialog(builder.create()); @@ -11831,7 +11933,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); if (reason == 0) { builder.setMessage(LocaleController.getString("ChannelCantOpenPrivate", R.string.ChannelCantOpenPrivate)); } else if (reason == 1) { @@ -12112,6 +12214,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean isVoted = object.isVoted(); TLRPC.TL_messageMediaPoll media = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (poll != null) { + object.messageOwner.translated = false; media.poll = poll; isQuiz = poll.quiz; } else if (media.poll != null) { @@ -12487,7 +12590,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (preferences.getBoolean("themehint", false)) { return; } - preferences.edit().putBoolean("themehint", true).commit(); + preferences.edit().putBoolean("themehint", true).apply(); boolean deleteTheme = (Boolean) args[2]; undoView.showWithAction(0, UndoView.ACTION_THEME_CHANGED, null, () -> { if (themeAccent != null) { @@ -12920,7 +13023,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } ChatMessageCell cell = (ChatMessageCell) view; MessageObject message = cell.getMessageObject(); - if (message != null && message.equals(hintMessageObject)) { + if (message != null && hintMessageObject != null && message.equals(hintMessageObject)) { cell.showHintButton(true, true, type); } } @@ -13023,7 +13126,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (showCount < 3) { if (Utilities.random.nextFloat() <= 0.2f) { showVoiceHint(false, chatActivityEnterView.isInVideoMode()); - preferences.edit().putInt(key, ++showCount).commit(); + preferences.edit().putInt(key, ++showCount).apply(); } } } @@ -13071,10 +13174,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!TextUtils.isEmpty(message)) { if (topUndoView != null) { if (type == MessagesController.PROMO_TYPE_PROXY) { - preferences.edit().putLong("proxychannel", dialog_id).commit(); + preferences.edit().putLong("proxychannel", dialog_id).apply(); } else if (type == MessagesController.PROMO_TYPE_PSA) { String psaType = getMessagesController().promoPsaType; - preferences.edit().putBoolean(psaType + "_shown", true).commit(); + preferences.edit().putBoolean(psaType + "_shown", true).apply(); } SpannableStringBuilder stringBuilder = new SpannableStringBuilder(message); MessageObject.addLinks(false, stringBuilder); @@ -13123,6 +13226,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (Build.VERSION.SDK_INT >= 23) { menu.removeItem(android.R.id.shareText); } + + menu.add(R.id.menu_translate, R.id.menu_translate, 5, LocaleController.getString("Translate", R.string.Translate)); + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(LocaleController.getString("Bold", R.string.Bold)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_bold, 6, stringBuilder); @@ -13132,7 +13238,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stringBuilder = new SpannableStringBuilder(LocaleController.getString("Mono", R.string.Mono)); stringBuilder.setSpan(new TypefaceSpan(Typeface.MONOSPACE), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_mono, 8, stringBuilder); - if (currentEncryptedChat == null || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { + if (currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { stringBuilder = new SpannableStringBuilder(LocaleController.getString("Strike", R.string.Strike)); TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; @@ -13147,6 +13253,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not menu.add(R.id.menu_groupbolditalic, R.id.menu_link, 11, LocaleController.getString("CreateLink", R.string.CreateLink)); menu.add(R.id.menu_groupbolditalic, R.id.menu_mention, 12, LocaleController.getString("CreateMention", R.string.CreateMention)); menu.add(R.id.menu_groupbolditalic, R.id.menu_regular, 13, LocaleController.getString("Regular", R.string.Regular)); + } private void updateScheduledInterface(boolean animated) { @@ -13440,6 +13547,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ValueAnimator animator = ValueAnimator.ofFloat(pinnedMessageView.getTranslationY(), 0); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { int position = -1; + @Override public void onAnimationUpdate(ValueAnimator animation) { float translationY = (float) animation.getAnimatedValue(); @@ -14010,7 +14118,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.setFieldFocused(false); } if (chatAttachAlert != null) { - if (!ignoreAttachOnPause){ + if (!ignoreAttachOnPause) { chatAttachAlert.onPause(); } else { ignoreAttachOnPause = false; @@ -14089,7 +14197,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not editor.remove("diditem" + dialog_id); editor.remove("diditemo" + dialog_id); } - editor.commit(); + editor.apply(); } if (currentUser != null) { @@ -14547,103 +14655,103 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || getMessageCaption(selectedObject, selectedObjectGroup) != null) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); - icons.add(R.drawable.msg_copy); + icons.add(R.drawable.baseline_content_copy_24); } items.add(LocaleController.getString("CancelSending", R.string.CancelSending)); options.add(24); - icons.add(R.drawable.msg_delete); + icons.add(R.drawable.baseline_delete_24); } else if (type == 0) { items.add(LocaleController.getString("Retry", R.string.Retry)); options.add(0); - icons.add(R.drawable.msg_retry); + icons.add(R.drawable.baseline_replay_24); items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); - icons.add(R.drawable.msg_delete); + icons.add(R.drawable.baseline_delete_24); } else if (type == 1) { if (currentChat != null) { if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(8); - icons.add(R.drawable.msg_reply); + icons.add(R.drawable.baseline_reply_24); } if (allowUnpin) { items.add(LocaleController.getString("UnpinMessage", R.string.UnpinMessage)); options.add(14); - icons.add(R.drawable.msg_unpin); + icons.add(R.drawable.deproko_baseline_pin_undo_24); } else if (allowPin) { items.add(LocaleController.getString("PinMessage", R.string.PinMessage)); options.add(13); - icons.add(R.drawable.msg_pin); + icons.add(R.drawable.deproko_baseline_pin_24); } if (message.canEditMessage(currentChat)) { items.add(LocaleController.getString("Edit", R.string.Edit)); options.add(12); - icons.add(R.drawable.msg_edit); + icons.add(R.drawable.baseline_edit_24); } if (selectedObject.contentType == 0 && !selectedObject.isMediaEmptyWebpage() && selectedObject.getId() > 0 && !selectedObject.isOut() && (currentChat != null || currentUser != null && currentUser.bot)) { items.add(LocaleController.getString("ReportChat", R.string.ReportChat)); options.add(23); - icons.add(R.drawable.msg_report); + icons.add(R.drawable.baseline_report_24); } if (message.canDeleteMessage(inScheduleMode, currentChat)) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); - icons.add(R.drawable.msg_delete); + icons.add(R.drawable.baseline_delete_24); } } else { if (selectedObject.getId() > 0 && allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(8); - icons.add(R.drawable.msg_reply); + icons.add(R.drawable.baseline_reply_24); } if (message.canDeleteMessage(inScheduleMode, currentChat)) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); - icons.add(R.drawable.msg_delete); + icons.add(R.drawable.baseline_delete_24); } } } else if (type == 20) { items.add(LocaleController.getString("Retry", R.string.Retry)); options.add(0); - icons.add(R.drawable.msg_retry); + icons.add(R.drawable.baseline_replay_24); items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); - icons.add(R.drawable.msg_copy); + icons.add(R.drawable.baseline_content_copy_24); items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); - icons.add(R.drawable.msg_delete); + icons.add(R.drawable.baseline_delete_24); } else { if (currentEncryptedChat == null) { if (inScheduleMode) { items.add(LocaleController.getString("MessageScheduleSend", R.string.MessageScheduleSend)); options.add(100); - icons.add(R.drawable.outline_send); + icons.add(R.drawable.deproko_baseline_send_24); } if (selectedObject.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) { TLRPC.TL_messageActionPhoneCall call = (TLRPC.TL_messageActionPhoneCall) message.messageOwner.action; items.add((call.reason instanceof TLRPC.TL_phoneCallDiscardReasonMissed || call.reason instanceof TLRPC.TL_phoneCallDiscardReasonBusy) && !message.isOutOwner() ? LocaleController.getString("CallBack", R.string.CallBack) : LocaleController.getString("CallAgain", R.string.CallAgain)); options.add(18); - icons.add(R.drawable.msg_callback); + icons.add(R.drawable.baseline_call_24); if (VoIPHelper.canRateCall(call)) { items.add(LocaleController.getString("CallMessageReportProblem", R.string.CallMessageReportProblem)); options.add(19); - icons.add(R.drawable.msg_fave); + icons.add(R.drawable.baseline_star_24); } } if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(8); - icons.add(R.drawable.msg_reply); + icons.add(R.drawable.baseline_reply_24); } if (selectedObject.type == 0 || selectedObject.isDice() || selectedObject.isAnimatedEmoji() || getMessageCaption(selectedObject, selectedObjectGroup) != null) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); - icons.add(R.drawable.msg_copy); + icons.add(R.drawable.baseline_content_copy_24); } if (!inScheduleMode && ChatObject.isChannel(currentChat)) { items.add(LocaleController.getString("CopyLink", R.string.CopyLink)); options.add(22); - icons.add(R.drawable.msg_link); + icons.add(R.drawable.baseline_link_24); } if (type == 2) { if (!inScheduleMode) { @@ -14670,119 +14778,139 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && MessageObject.isNewGifDocument(selectedObject.messageOwner.media.webpage.document)) { items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); options.add(11); - icons.add(R.drawable.msg_gif); + icons.add(R.drawable.deproko_baseline_gif_24); } } else if (type == 4) { if (selectedObject.isVideo()) { if (!selectedObject.needDrawBluredPreview()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(4); - icons.add(R.drawable.msg_gallery); + icons.add(R.drawable.baseline_image_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); - icons.add(R.drawable.msg_shareout); + icons.add(R.drawable.baseline_share_24); } } else if (selectedObject.isMusic()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(10); - icons.add(R.drawable.msg_download); + icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); - icons.add(R.drawable.msg_shareout); + icons.add(R.drawable.baseline_share_24); } else if (selectedObject.getDocument() != null) { if (MessageObject.isNewGifDocument(selectedObject.getDocument())) { items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); options.add(11); - icons.add(R.drawable.msg_gif); + icons.add(R.drawable.deproko_baseline_gif_24); } items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); - icons.add(R.drawable.msg_download); + icons.add(R.drawable.baseline_file_download_24); if (NekoConfig.showDeleteDownloadedFile) { items.add(LocaleController.getString("DeleteDownloadedFile", R.string.DeleteDownloadedFile)); options.add(91); - icons.add(R.drawable.menu_clearcache); + icons.add(R.drawable.baseline_delete_sweep_24); } items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); - icons.add(R.drawable.msg_shareout); + icons.add(R.drawable.baseline_share_24); } else { if (!selectedObject.needDrawBluredPreview()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(4); - icons.add(R.drawable.msg_gallery); + icons.add(R.drawable.baseline_image_24); } } } else if (type == 5) { items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); options.add(5); - icons.add(R.drawable.msg_language); + icons.add(R.drawable.baseline_language_24); items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); - icons.add(R.drawable.msg_download); + icons.add(R.drawable.baseline_file_download_24); if (NekoConfig.showDeleteDownloadedFile) { items.add(LocaleController.getString("DeleteDownloadedFile", R.string.DeleteDownloadedFile)); options.add(91); - icons.add(R.drawable.menu_clearcache); + icons.add(R.drawable.baseline_delete_sweep_24); } items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); - icons.add(R.drawable.msg_shareout); + icons.add(R.drawable.baseline_share_24); } else if (type == 10) { items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); options.add(5); - icons.add(R.drawable.msg_theme); + icons.add(R.drawable.baseline_palette_24); items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); - icons.add(R.drawable.msg_download); + icons.add(R.drawable.baseline_file_download_24); if (NekoConfig.showDeleteDownloadedFile) { items.add(LocaleController.getString("DeleteDownloadedFile", R.string.DeleteDownloadedFile)); options.add(91); - icons.add(R.drawable.menu_clearcache); + icons.add(R.drawable.baseline_delete_sweep_24); } items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); - icons.add(R.drawable.msg_shareout); + icons.add(R.drawable.baseline_share_24); + } else if (type == 21 || type == 22) { + options.add(5); + if (type == 21) { + items.add(LocaleController.getString("ImportProxyList", R.string.ImportProxyList)); + icons.add(R.drawable.baseline_security_24); + } else { + items.add(LocaleController.getString("ImportStickersList", R.string.ImportStickersList)); + icons.add(R.drawable.deproko_baseline_stickers_filled_24); + } + items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + options.add(10); + icons.add(R.drawable.baseline_file_download_24); + if (NekoConfig.showDeleteDownloadedFile) { + items.add(LocaleController.getString("DeleteDownloadedFile", R.string.DeleteDownloadedFile)); + options.add(91); + icons.add(R.drawable.baseline_delete_sweep_24); + } + items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + options.add(6); + icons.add(R.drawable.baseline_share_24); } else if (type == 6) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(7); - icons.add(R.drawable.msg_gallery); + icons.add(R.drawable.baseline_image_24); items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); - icons.add(R.drawable.msg_download); + icons.add(R.drawable.baseline_file_download_24); if (NekoConfig.showDeleteDownloadedFile) { items.add(LocaleController.getString("DeleteDownloadedFile", R.string.DeleteDownloadedFile)); options.add(91); - icons.add(R.drawable.menu_clearcache); + icons.add(R.drawable.baseline_delete_sweep_24); } items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); - icons.add(R.drawable.msg_shareout); + icons.add(R.drawable.baseline_share_24); } else if (type == 7) { if (selectedObject.isMask()) { items.add(LocaleController.getString("AddToMasks", R.string.AddToMasks)); options.add(9); - icons.add(R.drawable.msg_sticker); + icons.add(R.drawable.deproko_baseline_stickers_24); } else { if (!selectedObject.isAnimatedSticker()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(87); - icons.add(R.drawable.msg_gallery); + icons.add(R.drawable.baseline_image_24); } items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); options.add(9); - icons.add(R.drawable.msg_sticker); + icons.add(R.drawable.deproko_baseline_stickers_24); TLRPC.Document document = selectedObject.getDocument(); if (!getMediaDataController().isStickerInFavorites(document)) { - if (getMediaDataController().canAddStickerToFavorites() && MessageObject.isStickerHasSet(document)) { + if (getMediaDataController().canAddStickerToFavorites()/* && MessageObject.isStickerHasSet(document)*/) { items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); options.add(20); - icons.add(R.drawable.msg_fave); + icons.add(R.drawable.baseline_star_24); } } else { items.add(LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites)); options.add(21); - icons.add(R.drawable.msg_unfave); + icons.add(R.drawable.baseline_star_24); } } } else if (type == 8) { @@ -14790,33 +14918,33 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (user != null && user.id != getUserConfig().getClientUserId() && getContactsController().contactsDict.get(user.id) == null) { items.add(LocaleController.getString("AddContactTitle", R.string.AddContactTitle)); options.add(15); - icons.add(R.drawable.msg_addcontact); + icons.add(R.drawable.baseline_person_add_24); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(16); - icons.add(R.drawable.msg_copy); + icons.add(R.drawable.baseline_content_copy_24); items.add(LocaleController.getString("Call", R.string.Call)); options.add(17); - icons.add(R.drawable.msg_callback); + icons.add(R.drawable.baseline_call_24); } } else if (type == 9) { if (!selectedObject.isAnimatedSticker()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(87); - icons.add(R.drawable.msg_gallery); + icons.add(R.drawable.baseline_image_24); } TLRPC.Document document = selectedObject.getDocument(); if (!getMediaDataController().isStickerInFavorites(document)) { - if (MessageObject.isStickerHasSet(document)) { - items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); - options.add(20); - icons.add(R.drawable.msg_fave); - } + //if (MessageObject.isStickerHasSet(document)) { + items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); + options.add(20); + icons.add(R.drawable.baseline_star_24); + //} } else { items.add(LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites)); options.add(21); - icons.add(R.drawable.msg_unfave); + icons.add(R.drawable.baseline_star_24); } } if (!inScheduleMode && !selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16) { @@ -14829,10 +14957,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!UserObject.isUserSelf(currentUser) && NekoConfig.showAddToSavedMessages) { items.add(LocaleController.getString("AddToSavedMessages", R.string.AddToSavedMessages)); options.add(93); - icons.add(R.drawable.menu_saved); + icons.add(R.drawable.baseline_bookmark_24); } boolean allowRepeat = currentUser != null - || (currentChat != null && !ChatObject.isNotInChat(currentChat) && ChatObject.canSendMessages(currentChat)); + || (currentChat != null && ChatObject.canSendMessages(currentChat)); if (allowRepeat && NekoConfig.showRepeat) { items.add(LocaleController.getString("Repeat", R.string.Repeat)); options.add(94); @@ -14841,27 +14969,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (!inScheduleMode) { boolean allowPrpr = currentUser != null - || (currentChat != null && !ChatObject.isNotInChat(currentChat) && ChatObject.canSendMessages(currentChat) && !currentChat.broadcast && + || (currentChat != null && ChatObject.canSendMessages(currentChat) && !currentChat.broadcast && message.isFromUser()); boolean allowViewHistory = currentUser == null && (currentChat != null && !currentChat.broadcast && message.isFromUser()); - if (allowPrpr && NekoConfig.showPrPr) { - items.add(LocaleController.getString("Prpr", R.string.Prpr)); - options.add(92); - icons.add(R.drawable.msg_prpr); - } + if (allowViewHistory && NekoConfig.showViewHistory) { items.add(LocaleController.getString("ViewUserHistory", R.string.ViewHistory)); options.add(90); - icons.add(R.drawable.menu_recent); + icons.add(R.drawable.baseline_schedule_24); } if (NekoConfig.showMessageDetails) { items.add(LocaleController.getString("MessageDetails", R.string.MessageDetails)); options.add(89); icons.add(R.drawable.menu_info); } - if ((!TextUtils.isEmpty(selectedObject.messageOwner.message) || selectedObject.type == MessageObject.TYPE_POLL) && NekoConfig.showTranslate) { - items.add(selectedObject.translated ? LocaleController.getString("UndoTranslate", R.string.UndoTranslate) : LocaleController.getString("Translate", R.string.Translate)); + if ((StrUtil.isNotBlank(selectedObject.messageOwner.message) || selectedObject.isPoll()) && NekoConfig.showTranslate) { + items.add(selectedObject.messageOwner.translated ? LocaleController.getString("UndoTranslate", R.string.UndoTranslate) : LocaleController.getString("Translate", R.string.Translate)); options.add(88); icons.add(R.drawable.ic_translate); } @@ -14869,102 +14993,106 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (allowUnpin) { items.add(LocaleController.getString("UnpinMessage", R.string.UnpinMessage)); options.add(14); - icons.add(R.drawable.msg_unpin); + icons.add(R.drawable.deproko_baseline_pin_undo_24); } else if (allowPin) { items.add(LocaleController.getString("PinMessage", R.string.PinMessage)); options.add(13); - icons.add(R.drawable.msg_pin); + icons.add(R.drawable.deproko_baseline_pin_24); } if (allowEdit) { items.add(LocaleController.getString("Edit", R.string.Edit)); options.add(12); - icons.add(R.drawable.msg_edit); + icons.add(R.drawable.baseline_edit_24); } if (inScheduleMode && selectedObject.canEditMessageScheduleTime(currentChat)) { items.add(LocaleController.getString("MessageScheduleEditTime", R.string.MessageScheduleEditTime)); options.add(102); - icons.add(R.drawable.msg_schedule); + icons.add(R.drawable.baseline_date_range_24); } if (!inScheduleMode && selectedObject.contentType == 0 && selectedObject.getId() > 0 && !selectedObject.isOut() && (currentChat != null || currentUser != null && currentUser.bot) - && NekoConfig.showReport) { + && NekoConfig.showReport) { items.add(LocaleController.getString("ReportChat", R.string.ReportChat)); options.add(23); - icons.add(R.drawable.msg_report); + icons.add(R.drawable.baseline_report_24); } if (message.canDeleteMessage(inScheduleMode, currentChat)) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); - icons.add(R.drawable.msg_delete); + icons.add(R.drawable.baseline_delete_24); } } else { if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(8); - icons.add(R.drawable.msg_reply); + icons.add(R.drawable.baseline_reply_24); } if (selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || getMessageCaption(selectedObject, selectedObjectGroup) != null) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); - icons.add(R.drawable.msg_copy); + icons.add(R.drawable.baseline_content_copy_24); } if (type == 4) { if (selectedObject.isVideo()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(4); - icons.add(R.drawable.msg_gallery); + icons.add(R.drawable.baseline_image_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); - icons.add(R.drawable.msg_shareout); + icons.add(R.drawable.baseline_share_24); } else if (selectedObject.isMusic()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(10); - icons.add(R.drawable.msg_download); + icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); - icons.add(R.drawable.msg_shareout); + icons.add(R.drawable.baseline_share_24); } else if (!selectedObject.isVideo() && selectedObject.getDocument() != null) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); - icons.add(R.drawable.msg_download); + icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); - icons.add(R.drawable.msg_shareout); + icons.add(R.drawable.baseline_share_24); } else { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(4); - icons.add(R.drawable.msg_gallery); + icons.add(R.drawable.baseline_image_24); } } else if (type == 5) { items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); options.add(5); - icons.add(R.drawable.msg_language); + icons.add(R.drawable.baseline_language_24); } else if (type == 10) { items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); options.add(5); - icons.add(R.drawable.msg_theme); + icons.add(R.drawable.baseline_palette_24); + } else if (type == 21) { + items.add(LocaleController.getString("ImportProxyList", R.string.ImportProxyList)); + options.add(5); + icons.add(R.drawable.proxy_on); } else if (type == 7) { items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); options.add(9); - icons.add(R.drawable.msg_sticker); + icons.add(R.drawable.deproko_baseline_stickers_24); } else if (type == 8) { TLRPC.User user = getMessagesController().getUser(selectedObject.messageOwner.media.user_id); if (user != null && user.id != getUserConfig().getClientUserId() && getContactsController().contactsDict.get(user.id) == null) { items.add(LocaleController.getString("AddContactTitle", R.string.AddContactTitle)); options.add(15); - icons.add(R.drawable.msg_addcontact); + icons.add(R.drawable.baseline_person_add_24); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(16); - icons.add(R.drawable.msg_copy); + icons.add(R.drawable.baseline_content_copy_24); items.add(LocaleController.getString("Call", R.string.Call)); options.add(17); - icons.add(R.drawable.msg_callback); + icons.add(R.drawable.baseline_call_24); } } items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); - icons.add(R.drawable.msg_delete); + icons.add(R.drawable.baseline_delete_24); } if (chatInfo != null && chatInfo.participants != null && chatInfo.participants.participants != null) { for (int a = 0; a < chatInfo.participants.participants.size(); a++) { @@ -14994,12 +15122,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (canEditAdmin && NekoConfig.showAdminActions) { items.add(editingAdmin ? LocaleController.getString("EditAdminRights", R.string.EditAdminRights) : LocaleController.getString("SetAsAdmin", R.string.SetAsAdmin)); - icons.add(R.drawable.actions_addadmin); + icons.add(R.drawable.baseline_stars_18); options.add(97); } if (canRestrict && NekoConfig.showChangePermissions) { items.add(LocaleController.getString("ChangePermissions", R.string.ChangePermissions)); - icons.add(R.drawable.actions_permissions); + icons.add(R.drawable.baseline_block_24); options.add(98); } } @@ -15092,13 +15220,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (selectedObject == null || i < 0 || i >= options.size()) { return false; } - if (processSelectedOptionLongClick(options.get(i))) { + + int r = processSelectedOptionLongClick(cell, options.get(i)); + + if (r == 2) { if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } - return true; } - return false; + return r > 0; }); } scrollView.addView(linearLayout, LayoutHelper.createScroll(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); @@ -15310,7 +15440,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updatePinnedMessageView(true); updateVisibleRows(); - if (!messageObject.scheduled && !getUserConfig().isBot) { + if (!messageObject.scheduled && !UserConfig.getInstance(currentAccount).isBot) { TLRPC.TL_messages_getMessageEditData req = new TLRPC.TL_messages_getMessageEditData(); req.peer = getMessagesController().getInputPeer((int) dialog_id); req.id = messageObject.getId(); @@ -15321,7 +15451,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setMessage(LocaleController.getString("EditMessageError", R.string.EditMessageError)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); showDialog(builder.create()); @@ -15408,6 +15538,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void saveStickerToGallery(MessageObject messageObject) { + String path = messageObject.messageOwner.attachPath; if (!TextUtils.isEmpty(path)) { File temp = new File(path); @@ -15428,9 +15559,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!TextUtils.isEmpty(path)) { try { Bitmap image = BitmapFactory.decodeFile(path); + Bitmap outB = image.copy(Bitmap.Config.ARGB_8888, true); + Canvas canvas = new Canvas(outB); + canvas.drawColor(Color.WHITE); + canvas.drawBitmap(image, 0, 0, null); if (image != null) { FileOutputStream stream = new FileOutputStream(path + ".png"); - image.compress(Bitmap.CompressFormat.PNG, 100, stream); + outB.compress(Bitmap.CompressFormat.PNG, 100, stream); stream.close(); MediaController.saveFile(path + ".png", getParentActivity(), 0, null, null); } @@ -15548,12 +15683,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setMessage(LocaleController.getString("IncorrectTheme", R.string.IncorrectTheme)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); showDialog(builder.create()); } - } else { + } else if (locFile.getName().toLowerCase().endsWith("xml")) { if (LocaleController.getInstance().applyLanguageFile(locFile, currentAccount)) { presentFragment(new LanguageSelectActivity()); } else { @@ -15564,11 +15699,34 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setMessage(LocaleController.getString("IncorrectLocalization", R.string.IncorrectLocalization)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); showDialog(builder.create()); } + } else if (locFile.getName().toLowerCase().endsWith(".nekox.json")) { + + File finalLocFile1 = locFile; + AlertUtil.showConfirm(getParentActivity(), + LocaleController.getString("ImportProxyList", R.string.ImportProxyList), + R.drawable.baseline_security_24, LocaleController.getString("Import", R.string.Import), + false, () -> { + String status = ProxyListActivity.processProxyListFile(getParentActivity(), finalLocFile1); + if (!StrUtil.isBlank(status)) { + presentFragment(new ProxyListActivity(status)); + } + }); + + } else if (locFile.getName().toLowerCase().endsWith(".nekox-stickers.json")) { + + File finalLocFile = locFile; + AlertUtil.showConfirm(getParentActivity(), + LocaleController.getString("ImportStickersList", R.string.ImportStickersList), + R.drawable.deproko_baseline_stickers_filled_24, LocaleController.getString("Import", R.string.Import), + false, () -> { + presentFragment(new StickersActivity(finalLocFile)); + }); + } } break; @@ -15766,7 +15924,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (response != null) { TLRPC.TL_exportedMessageLink exportedMessageLink = (TLRPC.TL_exportedMessageLink) response; try { - android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + ClipboardManager clipboard = (ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText("label", exportedMessageLink.link); clipboard.setPrimaryClip(clip); if (exportedMessageLink.link.contains("/c/")) { @@ -15867,7 +16025,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); break; - } case 87: { + } + case 87: { if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; @@ -15877,129 +16036,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } saveStickerToGallery(selectedObject); break; - } case 88: { - if (NekoConfig.translationProvider < 0) { - if (selectedObject.type == MessageObject.TYPE_POLL) { - TLRPC.Poll poll = ((TLRPC.TL_messageMediaPoll) selectedObject.messageOwner.media).poll; - StringBuilder sb = new StringBuilder(); - sb.append(poll.question); - sb.append("\n"); - sb.append("--------"); - for (TLRPC.TL_pollAnswer answer: poll.answers) { - sb.append("\n"); - sb.append(answer.text); - } - TranslateBottomSheet.show(getParentActivity(), sb.toString()); - } else { - TranslateBottomSheet.show(getParentActivity(), selectedObject.messageOwner.message); - } - } else { - ChatMessageCell messageCell = null; - int count = chatListView.getChildCount(); - for (int a = 0; a < count; a++) { - View child = chatListView.getChildAt(a); - if (child instanceof ChatMessageCell) { - ChatMessageCell cell = (ChatMessageCell) child; - if (cell.getMessageObject() == selectedObject) { - messageCell = cell; - break; - } - } - } - if (selectedObject.translated){ - if (messageCell != null && selectedObject.originalMessage != null) { - if (selectedObject.originalMessage instanceof String) { - selectedObject.messageOwner.message = (String) selectedObject.originalMessage; - } else if (selectedObject.originalMessage instanceof TLRPC.TL_poll) { - ((TLRPC.TL_messageMediaPoll) selectedObject.messageOwner.media).poll = (TLRPC.TL_poll) selectedObject.originalMessage; - } - MessageHelper.resetMessageContent(selectedObject, messageCell); - chatAdapter.updateRowWithMessageObject(selectedObject, true); - selectedObject.translated = false; - } - } else { - Object original = selectedObject.type == MessageObject.TYPE_POLL ? ((TLRPC.TL_messageMediaPoll) selectedObject.messageOwner.media).poll : selectedObject.messageOwner.message; - selectedObject.originalMessage = original; - ChatMessageCell finalMessageCell = messageCell; - int finalOption = option; - Translator.translate(original, new Translator.TranslateCallBack() { - @Override - public void onSuccess(Object translation) { - if (finalMessageCell != null) { - MessageObject messageObject = finalMessageCell.getMessageObject(); - if (translation instanceof String) { - messageObject.messageOwner.message = original + - "\n" + - "--------" + - "\n" + - translation; - } else if (translation instanceof TLRPC.TL_poll) { - ((TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media).poll = (TLRPC.TL_poll) translation; - } - MessageHelper.resetMessageContent(messageObject, finalMessageCell); - chatAdapter.updateRowWithMessageObject(messageObject, true); - messageObject.translated = true; - } - } + } + case 88: { - @Override - public void onError(Throwable e) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - if (e != null && e.getLocalizedMessage() != null) { - builder.setTitle(LocaleController.getString("TranslateFailed", R.string.TranslateFailed)); - builder.setMessage(e.getLocalizedMessage()); - } else { - builder.setMessage(LocaleController.getString("TranslateFailed", R.string.TranslateFailed)); - } - builder.setNeutralButton(LocaleController.getString("TranslationProvider", R.string.TranslationProvider), (dialog, which) -> showDialog(NekoGeneralSettingsActivity.getTranslationProviderAlert(getParentActivity()))); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showDialog(builder.create()); - } + MessageTransKt.translateMessages(this, new MessageObject[] { selectedObject }); - @Override - public void onUnsupported() { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setMessage(LocaleController.getString("TranslateApiUnsupported", R.string.TranslateApiUnsupported)); - builder.setPositiveButton(LocaleController.getString("TranslationProvider", R.string.TranslationProvider), (dialog, which) -> showDialog(NekoGeneralSettingsActivity.getTranslationProviderAlert(getParentActivity()))); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); - } - }); - } - } break; - } case 89: { + + } + case 89: { presentFragment(new MessageDetailsActivity(selectedObject)); break; - } case 90: { - TLRPC.User user = getMessagesController().getUser(selectedObject.messageOwner.from_id); + } + case 90: { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(selectedObject.messageOwner.from_id); getMediaDataController().searchMessagesInChat("", dialog_id, mergeDialogId, classGuid, 0, user); showMessagesSearchListView(true); break; - } case 92: { - TLRPC.User user = getMessagesController().getUser(selectedObject.messageOwner.from_id); - if (user.username != null) { - getSendMessagesHelper().sendMessage("/prpr@" + user.username, dialog_id, selectedObject, null, false, - null, null, null, true, 0); - } else { - SpannableString spannableString = new SpannableString("/prpr@" + user.first_name); - spannableString.setSpan(new URLSpanUserMention(Integer.toString(user.id), 1), 6, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - CharSequence[] cs = new CharSequence[]{spannableString}; - boolean supportsSendingNewEntities = true; - long peer = getDialogId(); - if ((int) peer == 0) { - int high_id = (int) (peer >> 32); - TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(high_id); - if (encryptedChat == null || AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) < 101) { - supportsSendingNewEntities = false; - } - } - ArrayList entities = getMediaDataController().getEntities(cs, supportsSendingNewEntities); - getSendMessagesHelper().sendMessage(spannableString.toString(), dialog_id, selectedObject, null, false, - entities, null, null, true, 0); - } - break; - } case 91: { + } + case 91: { if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; @@ -16041,17 +16096,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messageCell.updateButtonState(false, true, false); } break; - } case 93: { - ArrayList messages = new ArrayList<>(); + } + case 93: { + ArrayList messages = new ArrayList<>(); messages.add(selectedObject); - forwardMessages(messages, false, true, 0, getUserConfig().getClientUserId()); + forwardMessages(messages, false, true, 0, UserConfig.getInstance(currentAccount).getClientUserId()); break; - } case 94: { - ArrayList messages = new ArrayList<>(); + } + case 94: { + ArrayList messages = new ArrayList<>(); messages.add(selectedObject); forwardMessages(messages, false, true, 0); break; - } case 95: { + } + case 95: { noForwardQuote = true; forwardingMessage = selectedObject; forwardingMessageGroup = selectedObjectGroup; @@ -16062,10 +16120,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fragment.setDelegate(this); presentFragment(fragment); break; - } case 97: { + } + case 97: { doAdminActions(97); break; - } case 98: { + } + case 98: { doAdminActions(98); break; } @@ -16121,10 +16181,48 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedObjectToEditCaption = null; } - private boolean processSelectedOptionLongClick(int option) { + private int processSelectedOptionLongClick(ActionBarMenuSubItem cell, int option) { switch (option) { + case 88: { + + ChatMessageCell messageCell = null; + int count = chatListView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = chatListView.getChildAt(a); + if (child instanceof ChatMessageCell) { + ChatMessageCell c = (ChatMessageCell) child; + if (c.getMessageObject() == selectedObject) { + messageCell = c; + break; + } + } + } + + if (selectedObject.messageOwner.translated) { + + return 0; + + } + + Translator.showTargetLangSelect(cell, (locale) -> { + + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + scrimPopupWindow = null; + scrimPopupWindowItems = null; + } + + MessageTransKt.translateMessages(this, new MessageObject[] { selectedObject }, locale); + + return Unit.INSTANCE; + + }); + + return 1; + + } case 94: { - ArrayList messages = new ArrayList<>(); + ArrayList messages = new ArrayList<>(); messages.add(selectedObject); if (selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || getMessageCaption(selectedObject, selectedObjectGroup) != null) { CharSequence caption = getMessageCaption(selectedObject, selectedObjectGroup); @@ -16133,7 +16231,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (caption != null) { StringBuilder toSend = new StringBuilder(); - for (int i = 0; i < caption.length(); i++){ + for (int i = 0; i < caption.length(); i++) { char c = caption.charAt(i); if (c == '我') { toSend.append('你'); @@ -16143,14 +16241,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not toSend.append(c); } } - getSendMessagesHelper().sendMessage(toSend.toString(), dialog_id, selectedObject, null, false, + SendMessagesHelper.getInstance(currentAccount).sendMessage(toSend.toString(), dialog_id, selectedObject, null, false, null, null, null, true, 0); - return true; + return 2; } } } } - return false; + return 0; } @Override @@ -16323,7 +16421,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int i = 0; i < n; i++) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getMessageObject() == unreadMessageObject) { - int unreadMessageIndex = messages.indexOf(unreadMessageObject); + int unreadMessageIndex = messages.indexOf(unreadMessageObject); if (unreadMessageIndex >= 0) { lastVisibleItem = chatAdapter.messagesStartRow + messages.indexOf(unreadMessageObject); top = chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom(); @@ -16435,7 +16533,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); if (message.type == 3) { builder.setMessage(LocaleController.getString("NoPlayerInstalled", R.string.NoPlayerInstalled)); @@ -16565,7 +16663,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not TLRPC.User user = getMessagesController().getUser(uid); if (ask) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); String name; if (user != null) { name = ContactsController.formatName(user.first_name, user.last_name); @@ -16575,7 +16673,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.setMessage(LocaleController.formatString("BotPermissionGameAlert", R.string.BotPermissionGameAlert, name)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { showOpenGameAlert(game, messageObject, urlStr, false, uid); - MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("askgame_" + uid, false).commit(); + MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("askgame_" + uid, false).apply(); }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); @@ -17128,7 +17226,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showPollSolution(cell.getMessageObject(), media.results); } else if (type == 1) { MessageObject messageObject = cell.getMessageObject(); - if (TextUtils.isEmpty(messageObject.messageOwner.fwd_from.psa_type)) { + if (messageObject.messageOwner.fwd_from == null || TextUtils.isEmpty(messageObject.messageOwner.fwd_from.psa_type)) { return; } CharSequence text = LocaleController.getString("PsaMessageInfo_" + messageObject.messageOwner.fwd_from.psa_type); @@ -17469,20 +17567,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not presentFragment(fragment); } } else if (message.type == 9 || message.type == 0) { + File locFile = null; + if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) { + File f = new File(message.messageOwner.attachPath); + if (f.exists()) { + locFile = f; + } + } + if (locFile == null) { + File f = FileLoader.getPathToMessage(message.messageOwner); + if (f.exists()) { + locFile = f; + } + } if (message.getDocumentName().toLowerCase().endsWith("attheme")) { - File locFile = null; - if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) { - File f = new File(message.messageOwner.attachPath); - if (f.exists()) { - locFile = f; - } - } - if (locFile == null) { - File f = FileLoader.getPathToMessage(message.messageOwner); - if (f.exists()) { - locFile = f; - } - } Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, message.getDocumentName(), null, true); if (themeInfo != null) { presentFragment(new ThemePreviewActivity(themeInfo)); @@ -17490,23 +17588,66 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { scrollToPositionOnRecreate = -1; } - } - boolean handled = false; - if (message.canPreviewDocument()) { - PhotoViewer.getInstance().setParentActivity(getParentActivity()); - PhotoViewer.getInstance().openPhoto(message, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, photoViewerProvider); - handled = true; - } - if (!handled) { - try { - AndroidUtilities.openForView(message, getParentActivity()); - } catch (Exception e) { - FileLog.e(e); - alertUserOpenError(message); + boolean handled = false; + if (message.canPreviewDocument()) { + PhotoViewer.getInstance().setParentActivity(getParentActivity()); + PhotoViewer.getInstance().openPhoto(message, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, photoViewerProvider); + handled = true; + } + if (!handled) { + try { + AndroidUtilities.openForView(message, getParentActivity()); + } catch (Exception e) { + FileLog.e(e); + alertUserOpenError(message); + } + } + } else if (locFile == null || !locFile.isFile()) { + + AlertUtil.showToast("FILE_NOT_FOUND"); + + } else if (message.getDocumentName().toLowerCase().endsWith(".nekox.json")) { + + File finalLocFile = locFile; + AlertUtil.showConfirm(getParentActivity(), + LocaleController.getString("ImportProxyList", R.string.ImportProxyList), + R.drawable.baseline_security_24, LocaleController.getString("Import", R.string.Import), + false, () -> { + String status = ProxyListActivity.processProxyListFile(getParentActivity(), finalLocFile); + if (!StrUtil.isBlank(status)) { + presentFragment(new ProxyListActivity(status)); + } + }); + + } else if (message.getDocumentName().toLowerCase().endsWith(".nekox-stickers.json")) { + + File finalLocFile = locFile; + AlertUtil.showConfirm(getParentActivity(), + LocaleController.getString("ImportStickersList", R.string.ImportStickersList), + R.drawable.deproko_baseline_stickers_filled_24, LocaleController.getString("Import", R.string.Import), false, () -> { + presentFragment(new StickersActivity(finalLocFile)); + }); + + } else { + boolean handled = false; + if (message.canPreviewDocument()) { + PhotoViewer.getInstance().setParentActivity(getParentActivity()); + PhotoViewer.getInstance().openPhoto(message, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, photoViewerProvider); + handled = true; + } + if (!handled) { + try { + AndroidUtilities.openForView(message, getParentActivity()); + } catch (Exception e) { + FileLog.e(e); + alertUserOpenError(message); + } } } } + } + @Override public void didPressInstantButton(ChatMessageCell cell, int type) { MessageObject messageObject = cell.getMessageObject(); @@ -17830,7 +17971,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); } } - if (fromUserBlocked){ + if (fromUserBlocked) { messageCell.setVisibility(View.GONE); } else { messageCell.setVisibility(View.VISIBLE); @@ -18065,7 +18206,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void notifyItemMoved(int fromPosition, int toPosition) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("notify item moved" + fromPosition + ":" + toPosition); + FileLog.d("notify item moved" + fromPosition + ":" + toPosition); } if (chatListView.getItemAnimator() != chatListItemAniamtor) { chatListView.setItemAnimator(chatListItemAniamtor); @@ -18229,7 +18370,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } public static boolean isClickableLink(String str) { - return str.startsWith("https://") || str.startsWith("@") || str.startsWith("#") || str.startsWith("$"); + return str.startsWith("https://") || str.startsWith("vmess://") || str.startsWith("vmess1://") || str.startsWith("ss://") || str.startsWith("ssr://") || str.startsWith("@") || str.startsWith("#") || str.startsWith("$"); } @Override @@ -18859,13 +19000,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not presentFragment(fragment); } - private void doAdminActions(int option){ + private void doAdminActions(int option) { int action = 0; - switch (option){ + switch (option) { case 97: action = 0; break; - case 98 : + case 98: action = 1; break; } @@ -18883,7 +19024,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (action == 1 && (channelParticipant instanceof TLRPC.TL_channelParticipantAdmin || participant instanceof TLRPC.TL_chatParticipantAdmin)) { AlertDialog.Builder builder2 = new AlertDialog.Builder(getParentActivity()); - builder2.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder2.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder2.setMessage(LocaleController.formatString("AdminWillBeRemoved", R.string.AdminWillBeRemoved, ContactsController.formatName(user.first_name, user.last_name))); int finalAction = action; builder2.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index 07739b5c2..91401acd3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -87,6 +87,7 @@ import androidx.core.view.inputmethod.InputConnectionCompat; import androidx.core.view.inputmethod.InputContentInfoCompat; import androidx.customview.widget.ExploreByTouchHelper; +import org.jetbrains.annotations.NotNull; import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -126,45 +127,77 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.concurrent.atomic.AtomicBoolean; +import kotlin.Unit; import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.transtale.TranslateBottomSheet; +import tw.nekomimi.nekogram.transtale.TranslateDb; +import tw.nekomimi.nekogram.transtale.Translator; +import tw.nekomimi.nekogram.transtale.TranslatorKt; +import tw.nekomimi.nekogram.utils.AlertUtil; public class ChatActivityEnterView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate { public interface ChatActivityEnterViewDelegate { void onMessageSend(CharSequence message, boolean notify, int scheduleDate); + void needSendTyping(); + void onTextChanged(CharSequence text, boolean bigChange); + void onTextSelectionChanged(int start, int end); + void onTextSpansChanged(CharSequence text); + void onAttachButtonHidden(); + void onAttachButtonShow(); + void onWindowSizeChanged(int size); + void onStickersTab(boolean opened); + void onMessageEditEnd(boolean loading); + void didPressAttachButton(); + void needStartRecordVideo(int state, boolean notify, int scheduleDate); + void needChangeVideoPreviewState(int state, float seekProgress); + void onSwitchRecordMode(boolean video); + void onPreAudioVideoRecord(); + void needStartRecordAudio(int state); + void needShowMediaBanHint(); + void onStickersExpandedChange(); + void onUpdateSlowModeButton(View button, boolean show, CharSequence time); + default void scrollToSendingMessage() { } + default void openScheduledMessages() { } + default boolean hasScheduledMessages() { return true; } + void onSendLongClick(); + void onAudioVideoInterfaceUpdated(); + default void bottomPanelTranslationYChanged(float translation) { } + default void prepareMessageSending() { } @@ -614,6 +647,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe drawable.stop(); invalidate(); } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -769,19 +803,19 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe public RecordCircle(Context context) { super(context); micDrawable = getResources().getDrawable(R.drawable.input_mic_pressed).mutate(); - micDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.MULTIPLY)); + micDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.SRC_IN)); cameraDrawable = getResources().getDrawable(R.drawable.input_video_pressed).mutate(); - cameraDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.MULTIPLY)); + cameraDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.SRC_IN)); sendDrawable = getResources().getDrawable(R.drawable.attach_send).mutate(); - sendDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.MULTIPLY)); + sendDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.SRC_IN)); micOutline = getResources().getDrawable(R.drawable.input_mic).mutate(); - micOutline.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + micOutline.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); cameraOutline = getResources().getDrawable(R.drawable.input_video).mutate(); - cameraOutline.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + cameraOutline.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); virtualViewHelper = new VirtualViewHelper(this); ViewCompat.setAccessibilityDelegate(this, virtualViewHelper); @@ -802,7 +836,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe lockOutlinePaint.setStrokeWidth(AndroidUtilities.dpf2(1.7f)); lockShadowDrawable = getResources().getDrawable(R.drawable.lock_round_shadow); - lockShadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoiceLockShadow), PorterDuff.Mode.MULTIPLY)); + lockShadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoiceLockShadow), PorterDuff.Mode.SRC_IN)); tooltipBackground = Theme.createRoundRectDrawable(AndroidUtilities.dp(5), Theme.getColor(Theme.key_chat_gifSaveHintBackground)); tooltipPaint.setTextSize(AndroidUtilities.dp(14)); @@ -936,7 +970,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe tooltipLayout = new StaticLayout(tooltipMessage, tooltipPaint, AndroidUtilities.dp(220), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true); int n = tooltipLayout.getLineCount(); tooltipWidth = 0; - for (int i = 0 ; i < n; i++) { + for (int i = 0; i < n; i++) { float w = tooltipLayout.getLineWidth(i); if (w > tooltipWidth) { tooltipWidth = w; @@ -1413,7 +1447,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe paintRecordWaveTin.setAlpha((int) (255 * CIRCLE_ALPHA_2)); tooltipPaint.setColor(Theme.getColor(Theme.key_chat_gifSaveHintText)); tooltipBackground = Theme.createRoundRectDrawable(AndroidUtilities.dp(5), Theme.getColor(Theme.key_chat_gifSaveHintBackground)); - tooltipBackgroundArrow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_gifSaveHintBackground), PorterDuff.Mode.MULTIPLY)); + tooltipBackgroundArrow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_gifSaveHintBackground), PorterDuff.Mode.SRC_IN)); lockBackgroundPaint.setColor(Theme.getColor(Theme.key_chat_messagePanelVoiceLockBackground)); lockPaint.setColor(Theme.getColor(Theme.key_chat_messagePanelVoiceLock)); @@ -1460,7 +1494,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe public void showWaves(boolean b, boolean animated) { if (!animated) { - wavesEnterAnimation = b? 1f : 0.5f; + wavesEnterAnimation = b ? 1f : 0.5f; } showWaves = b; } @@ -1878,7 +1912,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } } }; - emojiButton[a].setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + emojiButton[a].setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); emojiButton[a].setScaleType(ImageView.ScaleType.CENTER_INSIDE); if (Build.VERSION.SDK_INT >= 21) { emojiButton[a].setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector))); @@ -1991,12 +2025,32 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe rectangle.bottom += AndroidUtilities.dp(1000); return super.requestRectangleOnScreen(rectangle); } + }; - messageEditText.setDelegate(() -> { - if (delegate != null) { - delegate.onTextSpansChanged(messageEditText.getText()); + messageEditText.setDelegate(new EditTextCaption.EditTextCaptionDelegate() { + + @Override public void onSpansChanged() { + if (delegate != null) { + delegate.onTextSpansChanged(messageEditText.getText()); + } } + + @Override public int getCurrentChat() { + + int chatId; + if (parentFragment.getCurrentChat() != null) { + chatId = parentFragment.getCurrentChat().id; + } else if (parentFragment.getCurrentUser() != null) { + chatId = parentFragment.getCurrentUser().id; + } else { + chatId = -1; + } + + return chatId; + } + }); + messageEditText.setWindowView(parentActivity.getWindow().getDecorView()); TLRPC.EncryptedChat encryptedChat = parentFragment != null ? parentFragment.getCurrentEncryptedChat() : null; messageEditText.setAllowTextEntitiesIntersection(supportsSendingNewEntities()); @@ -2028,7 +2082,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (keyEvent.getAction() == 1) { if (currentPopupContentType == 1 && botButtonsMessageObject != null) { SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); - preferences.edit().putInt("hidekeyboard_" + dialog_id, botButtonsMessageObject.getId()).commit(); + preferences.edit().putInt("hidekeyboard_" + dialog_id, botButtonsMessageObject.getId()).apply(); } if (searchingType != 0) { searchingType = 0; @@ -2135,8 +2189,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (parentFragment != null) { Drawable drawable1 = context.getResources().getDrawable(R.drawable.input_calendar1).mutate(); Drawable drawable2 = context.getResources().getDrawable(R.drawable.input_calendar2).mutate(); - drawable1.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); - drawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_recordedVoiceDot), PorterDuff.Mode.MULTIPLY)); + drawable1.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); + drawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_recordedVoiceDot), PorterDuff.Mode.SRC_IN)); CombinedDrawable combinedDrawable = new CombinedDrawable(drawable1, drawable2); scheduledButton = new ImageView(context); @@ -2163,7 +2217,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe frameLayout.addView(attachLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 48, Gravity.BOTTOM | Gravity.RIGHT)); botButton = new ImageView(context); - botButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + botButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); botButton.setImageResource(R.drawable.input_bot2); botButton.setScaleType(ImageView.ScaleType.CENTER); if (Build.VERSION.SDK_INT >= 21) { @@ -2181,7 +2235,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (!isPopupShowing() || currentPopupContentType != 1) { showPopup(1, 1); SharedPreferences preferences1 = MessagesController.getMainSettings(currentAccount); - preferences1.edit().remove("hidekeyboard_" + dialog_id).commit(); + preferences1.edit().remove("hidekeyboard_" + dialog_id).apply(); } else { if (currentPopupContentType == 1 && botButtonsMessageObject != null) { SharedPreferences preferences1 = MessagesController.getMainSettings(currentAccount); @@ -2202,7 +2256,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe notifyButton = new ImageView(context); notifyButton.setImageResource(silent ? R.drawable.input_notify_off : R.drawable.input_notify_on); notifyButton.setContentDescription(silent ? LocaleController.getString("AccDescrChanSilentOn", R.string.AccDescrChanSilentOn) : LocaleController.getString("AccDescrChanSilentOff", R.string.AccDescrChanSilentOff)); - notifyButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + notifyButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); notifyButton.setScaleType(ImageView.ScaleType.CENTER); if (Build.VERSION.SDK_INT >= 21) { notifyButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector))); @@ -2239,8 +2293,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe }); attachButton = new ImageView(context); - attachButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); - attachButton.setImageResource(R.drawable.input_attach); + attachButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); + attachButton.setImageResource(R.drawable.deproko_baseline_attach_26); attachButton.setScaleType(ImageView.ScaleType.CENTER); if (Build.VERSION.SDK_INT >= 21) { attachButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector))); @@ -2552,7 +2606,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe audioSendButton = new ImageView(context); audioSendButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - audioSendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + audioSendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); audioSendButton.setImageResource(R.drawable.input_mic); audioSendButton.setPadding(0, 0, AndroidUtilities.dp(4), 0); audioSendButton.setContentDescription(LocaleController.getString("AccDescrVoiceMessage", R.string.AccDescrVoiceMessage)); @@ -2563,7 +2617,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (isChat) { videoSendButton = new ImageView(context); videoSendButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - videoSendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + videoSendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); videoSendButton.setImageResource(R.drawable.input_video); videoSendButton.setPadding(0, 0, AndroidUtilities.dp(4), 0); videoSendButton.setContentDescription(LocaleController.getString("AccDescrVideoMessage", R.string.AccDescrVideoMessage)); @@ -2581,7 +2635,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe cancelBotButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); cancelBotButton.setImageDrawable(progressDrawable = new CloseProgressDrawable2()); cancelBotButton.setContentDescription(LocaleController.getString("Cancel", R.string.Cancel)); - progressDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelCancelInlineBot), PorterDuff.Mode.MULTIPLY)); + progressDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelCancelInlineBot), PorterDuff.Mode.SRC_IN)); cancelBotButton.setSoundEffectsEnabled(false); cancelBotButton.setScaleX(0.1f); cancelBotButton.setScaleY(0.1f); @@ -2653,10 +2707,10 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } prevColorType = colorType; drawableColor = color; - sendButtonDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelSend), PorterDuff.Mode.MULTIPLY)); + sendButtonDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelSend), PorterDuff.Mode.SRC_IN)); int c = Theme.getColor(Theme.key_chat_messagePanelIcons); - inactinveSendButtonDrawable.setColorFilter(new PorterDuffColorFilter(Color.argb(0xb4, Color.red(c), Color.green(c), Color.blue(c)), PorterDuff.Mode.MULTIPLY)); - sendButtonInverseDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.MULTIPLY)); + inactinveSendButtonDrawable.setColorFilter(new PorterDuffColorFilter(Color.argb(0xb4, Color.red(c), Color.green(c), Color.blue(c)), PorterDuff.Mode.SRC_IN)); + sendButtonInverseDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.SRC_IN)); } if (animationProgress < 1.0f) { long newTime = SystemClock.elapsedRealtime(); @@ -2794,7 +2848,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe Drawable drawable = Theme.createCircleDrawable(AndroidUtilities.dp(16), Theme.getColor(Theme.key_chat_messagePanelSend)); Drawable checkDrawable = context.getResources().getDrawable(R.drawable.input_done).mutate(); - checkDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.MULTIPLY)); + checkDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.SRC_IN)); CombinedDrawable combinedDrawable = new CombinedDrawable(drawable, checkDrawable, 0, AndroidUtilities.dp(1)); combinedDrawable.setCustomSize(AndroidUtilities.dp(32), AndroidUtilities.dp(32)); @@ -2852,7 +2906,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (child == topView) { canvas.save(); - canvas.clipRect(0, animatedTop, getMeasuredWidth(), animatedTop + child.getLayoutParams().height + AndroidUtilities.dp(2)); + canvas.clipRect(0, animatedTop, getMeasuredWidth(), animatedTop + child.getLayoutParams().height + AndroidUtilities.dp(2)); } boolean result = super.drawChild(canvas, child, drawingTime); if (child == topView) { @@ -2913,33 +2967,62 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe }); sendPopupLayout.setShowedFromBotton(false); - for (int a = 0; a < 2; a++) { - if (a == 1 && (UserObject.isUserSelf(user) || slowModeTimer > 0 && !isInScheduleMode())) { + for (int a = 0; a < 3; a++) { + if (a == 2 && (UserObject.isUserSelf(user) || slowModeTimer > 0 && !isInScheduleMode())) { continue; } int num = a; ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getContext()); if (num == 0) { - if (UserObject.isUserSelf(user)) { - cell.setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.msg_schedule); - } else { - cell.setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); - } + cell.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate); } else if (num == 1) { + if (UserObject.isUserSelf(user)) { + cell.setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.baseline_date_range_24); + } else { + cell.setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.baseline_date_range_24); + } + } else if (num == 2) { cell.setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); } cell.setMinimumWidth(AndroidUtilities.dp(196)); sendPopupLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * a, 0, 0)); + + int chatId; + if (chat != null) { + chatId = chat.id; + } else if (user != null) { + chatId = user.id; + } else { + chatId = -1; + } + cell.setOnClickListener(v -> { if (sendPopupWindow != null && sendPopupWindow.isShowing()) { sendPopupWindow.dismiss(); } if (num == 0) { + translateComment(TranslateDb.getChatLanguage(chatId, TranslatorKt.getCode2Locale(NekoConfig.translateInputLang))); + } + if (num == 1) { AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), this::sendMessageInternal); - } else if (num == 1) { + } else if (num == 2) { sendMessageInternal(false, 0); } }); + cell.setOnLongClickListener(v -> { + if (num == 0) { + Translator.showTargetLangSelect(cell, true, (locale) -> { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + translateComment(locale); + TranslateDb.saveChatLanguage(chatId, locale); + return Unit.INSTANCE; + }); + return true; + } + return false; + }); } sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { @@ -2981,6 +3064,59 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe return false; } + private void translateComment(Locale target) { + + if (NekoConfig.translationProvider < 0) { + TranslateBottomSheet.show(parentActivity, messageEditText.getText().toString()); + } else { + + TranslateDb db = TranslateDb.forLocale(target); + String origin = messageEditText.getText().toString(); + + if (db.contains(origin)) { + + String translated = db.query(origin); + messageEditText.setText(translated); + + return; + + } + + Translator.translate(target, origin, new Translator.Companion.TranslateCallBack() { + + final AtomicBoolean cancel = new AtomicBoolean(); + AlertDialog status = AlertUtil.showProgress(parentActivity); + + { + + status.setOnCancelListener((__) -> { + cancel.set(true); + }); + + status.show(); + + } + + @Override public void onSuccess(@NotNull String translation) { + status.dismiss(); + messageEditText.setText(translation); + } + + @Override public void onFailed(boolean unsupported, @NotNull String message) { + status.dismiss(); + AlertUtil.showTransFailedDialog(parentActivity, unsupported, message, () -> { + status = AlertUtil.showProgress(parentActivity); + status.show(); + Translator.translate(origin, this); + }); + } + + }); + + } + + } + public boolean isSendButtonVisible() { return sendButton.getVisibility() == VISIBLE; } @@ -5675,14 +5811,14 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } if (botReplyMarkup != null) { if (isPopupShowing() && currentPopupContentType == 1) { - botButton.setImageResource(R.drawable.input_keyboard); + botButton.setImageResource(R.drawable.baseline_keyboard_24); botButton.setContentDescription(LocaleController.getString("AccDescrShowKeyboard", R.string.AccDescrShowKeyboard)); } else { - botButton.setImageResource(R.drawable.input_bot2); + botButton.setImageResource(R.drawable.deproko_baseline_bots_24); botButton.setContentDescription(LocaleController.getString("AccDescrBotKeyboard", R.string.AccDescrBotKeyboard)); } } else { - botButton.setImageResource(R.drawable.input_bot1); + botButton.setImageResource(R.drawable.deproko_baseline_bots_command_26); botButton.setContentDescription(LocaleController.getString("AccDescrBotCommands", R.string.AccDescrBotCommands)); } } else { @@ -6446,13 +6582,13 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe emojiButtonAnimation = null; } if (nextIcon == 0) { - emojiButton[animated ? 1 : 0].setImageResource(R.drawable.input_keyboard); + emojiButton[animated ? 1 : 0].setImageResource(R.drawable.baseline_keyboard_24); } else if (nextIcon == 1) { - emojiButton[animated ? 1 : 0].setImageResource(R.drawable.input_smile); + emojiButton[animated ? 1 : 0].setImageResource(R.drawable.baseline_emoticon_24); } else if (nextIcon == 2) { - emojiButton[animated ? 1 : 0].setImageResource(R.drawable.input_sticker); + emojiButton[animated ? 1 : 0].setImageResource(R.drawable.deproko_baseline_stickers_24); } else if (nextIcon == 3) { - emojiButton[animated ? 1 : 0].setImageResource(R.drawable.input_gif); + emojiButton[animated ? 1 : 0].setImageResource(R.drawable.deproko_baseline_gif_24); } emojiButton[animated ? 1 : 0].setTag(nextIcon == 2 ? 1 : null); currentEmojiIcon = nextIcon; 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 87abc4477..5dcae1c8d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -46,10 +46,17 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.Keep; +import androidx.core.graphics.ColorUtils; +import androidx.dynamicanimation.animation.DynamicAnimation; +import androidx.dynamicanimation.animation.SpringAnimation; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.jetbrains.annotations.NotNull; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; -import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; @@ -78,13 +85,16 @@ import org.telegram.ui.PhotoPickerSearchActivity; import java.util.ArrayList; import java.util.HashMap; +import java.util.Locale; +import java.util.concurrent.atomic.AtomicBoolean; -import androidx.annotation.Keep; -import androidx.core.graphics.ColorUtils; -import androidx.dynamicanimation.animation.DynamicAnimation; -import androidx.dynamicanimation.animation.SpringAnimation; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; +import kotlin.Unit; +import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.transtale.TranslateBottomSheet; +import tw.nekomimi.nekogram.transtale.TranslateDb; +import tw.nekomimi.nekogram.transtale.Translator; +import tw.nekomimi.nekogram.transtale.TranslatorKt; +import tw.nekomimi.nekogram.utils.AlertUtil; public class ChatAttachAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate, BottomSheet.BottomSheetDelegateInterface { @@ -1028,7 +1038,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N shadow = new View(context); shadow.setBackgroundResource(R.drawable.attach_shadow); - shadow.getBackground().setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); + shadow.getBackground().setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.SRC_IN)); containerView.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 84)); buttonsRecyclerView = new RecyclerListView(context) { @@ -1162,14 +1172,14 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N writeButtonDrawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_dialogFloatingButton), Theme.getColor(Build.VERSION.SDK_INT >= 21 ? Theme.key_dialogFloatingButtonPressed : Theme.key_dialogFloatingButton)); 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)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.SRC_IN)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, writeButtonDrawable, 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56)); writeButtonDrawable = combinedDrawable; } writeButton.setBackgroundDrawable(writeButtonDrawable); writeButton.setImageResource(R.drawable.attach_send); - writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.MULTIPLY)); + writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.SRC_IN)); writeButton.setScaleType(ImageView.ScaleType.CENTER); if (Build.VERSION.SDK_INT >= 21) { writeButton.setOutlineProvider(new ViewOutlineProvider() { @@ -1237,35 +1247,42 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N }); sendPopupLayout.setShowedFromBotton(false); - itemCells = new ActionBarMenuSubItem[2]; + itemCells = new ActionBarMenuSubItem[3]; int i = 0; - for (int a = 0; a < 2; a++) { - if (a == 0) { + for (int a = 0; a < 3; a++) { + if (a == 1) { if (!currentAttachLayout.canScheduleMessages()) { continue; } - } else if (a == 1 && UserObject.isUserSelf(user)) { + } else if (a == 2 && UserObject.isUserSelf(user)) { continue; } int num = a; itemCells[a] = new ActionBarMenuSubItem(getContext()); if (num == 0) { - if (UserObject.isUserSelf(user)) { - itemCells[a].setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.msg_schedule); - } else { - itemCells[a].setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); - } + itemCells[a].setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate); } else if (num == 1) { + if (UserObject.isUserSelf(user)) { + itemCells[a].setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.baseline_date_range_24); + } else { + itemCells[a].setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.baseline_date_range_24); + } + } else if (num == 2) { itemCells[a].setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); } itemCells[a].setMinimumWidth(AndroidUtilities.dp(196)); sendPopupLayout.addView(itemCells[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * i, 0, 0)); + + int chatId = chat == null ? -1 : chat.id; + itemCells[a].setOnClickListener(v -> { if (sendPopupWindow != null && sendPopupWindow.isShowing()) { sendPopupWindow.dismiss(); } if (num == 0) { + translateComment(parentFragment.getParentActivity(), TranslateDb.getChatLanguage(chatId, TranslatorKt.getCode2Locale(NekoConfig.translateInputLang))); + } else if (num == 1) { AlertsCreator.createScheduleDatePickerDialog(getContext(), chatActivity.getDialogId(), (notify, scheduleDate) -> { if (currentAttachLayout == photoLayout) { sendPressed(notify, scheduleDate); @@ -1274,7 +1291,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N dismiss(); } }); - } else if (num == 1) { + } else if (num == 2) { if (currentAttachLayout == photoLayout) { sendPressed(false, 0); } else { @@ -1283,6 +1300,21 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } } }); + + itemCells[a].setOnLongClickListener(v -> { + if (num == 0) { + Translator.showTargetLangSelect(itemCells[num], true, (locale) -> { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + translateComment(parentFragment.getParentActivity(), locale); + TranslateDb.saveChatLanguage(chatId, locale); + return Unit.INSTANCE; + }); + return true; + } + return false; + }); i++; } @@ -1336,6 +1368,59 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N containerView.addView(selectedCountView, LayoutHelper.createFrame(42, 24, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -8, 9)); } + private void translateComment(Context ctx, Locale target) { + + if (NekoConfig.translationProvider < 0) { + TranslateBottomSheet.show(ctx, commentTextView.getText().toString()); + } else { + + TranslateDb db = TranslateDb.forLocale(target); + String origin = commentTextView.getText().toString(); + + if (db.contains(origin)) { + + String translated = db.query(origin); + commentTextView.getEditText().setText(translated); + + return; + + } + + Translator.translate(target, origin, new Translator.Companion.TranslateCallBack() { + + final AtomicBoolean cancel = new AtomicBoolean(); + AlertDialog status = AlertUtil.showProgress(ctx); + + { + + status.setOnCancelListener((__) -> { + cancel.set(true); + }); + + status.show(); + + } + + @Override public void onSuccess(@NotNull String translation) { + status.dismiss(); + commentTextView.getEditText().setText(translation); + } + + @Override public void onFailed(boolean unsupported, @NotNull String message) { + status.dismiss(); + AlertUtil.showTransFailedDialog(ctx, unsupported, message, () -> { + status = AlertUtil.showProgress(ctx); + status.show(); + Translator.translate(origin, this); + }); + } + + }); + + } + + } + @Override public void show() { super.show(); @@ -1381,7 +1466,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N TLRPC.Chat chat = chatActivity.getCurrentChat(); TLRPC.User user = chatActivity.getCurrentUser(); if (user != null || ChatObject.isChannel(chat) && chat.megagroup || !ChatObject.isChannel(chat)) { - MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + chatActivity.getDialogId(), !notify).commit(); + MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + chatActivity.getDialogId(), !notify).apply(); } } applyCaption(); @@ -1775,7 +1860,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N Theme.setSelectorDrawableColor(writeButtonDrawable, Theme.getColor(Theme.key_dialogFloatingButton), false); Theme.setSelectorDrawableColor(writeButtonDrawable, Theme.getColor(Build.VERSION.SDK_INT >= 21 ? Theme.key_dialogFloatingButtonPressed : Theme.key_dialogFloatingButton), true); - writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.MULTIPLY)); + writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.SRC_IN)); actionBarShadow.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java index 89fc795a2..5016fec64 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java @@ -32,6 +32,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; +import org.jetbrains.annotations.NotNull; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; @@ -40,6 +41,14 @@ import org.telegram.messenger.R; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.Theme; +import cn.hutool.core.util.StrUtil; +import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.transtale.TranslateBottomSheet; +import tw.nekomimi.nekogram.transtale.TranslateDb; +import tw.nekomimi.nekogram.transtale.Translator; +import tw.nekomimi.nekogram.transtale.TranslatorKt; +import tw.nekomimi.nekogram.utils.AlertUtil; + public class EditTextCaption extends EditTextBoldCursor { private String caption; @@ -57,6 +66,8 @@ public class EditTextCaption extends EditTextBoldCursor { public interface EditTextCaptionDelegate { void onSpansChanged(); + + int getCurrentChat(); } public EditTextCaption(Context context) { @@ -112,6 +123,69 @@ public class EditTextCaption extends EditTextBoldCursor { applyTextStyleToSelection(new TextStyleSpan(run)); } + private String replaceAt(String origin, int start, int end, String translation) { + + String trans = origin.substring(0, start); + + trans += translation; + + trans += origin.substring(end); + + return trans; + + } + + public void makeSelectedTranslate() { + + int start = getSelectionStart(); + int end = getSelectionEnd(); + + String origin = getText().toString(); + String text = getText().subSequence(start, end).toString(); + + if (StrUtil.isBlank(origin)) return; + + TranslateDb db = TranslateDb.currentInputTarget(); + + if (db.contains(text)) { + + setText(replaceAt(origin, start, end, TranslateDb.currentInputTarget().query(text))); + + } else { + + if (NekoConfig.translationProvider < 0) { + TranslateBottomSheet.show(getContext(), text); + } else { + + Translator.translate(TranslateDb.getChatLanguage(delegate.getCurrentChat(), TranslatorKt.getCode2Locale(NekoConfig.translateInputLang)), text, new Translator.Companion.TranslateCallBack() { + + AlertDialog status = AlertUtil.showProgress(getContext()); + + { + status.show(); + } + + @Override public void onSuccess(@NotNull String translation) { + status.dismiss(); + setText(replaceAt(origin, start, end, translation)); + } + + @Override public void onFailed(boolean unsupported, @NotNull String message) { + status.dismiss(); + AlertUtil.showTransFailedDialog(getContext(), unsupported, message, () -> { + status = AlertUtil.showProgress(getContext()); + status.show(); + Translator.translate(text, this); + }); + } + + }); + + } + + } + + } public void makeSelectedMention() { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); @@ -355,11 +429,14 @@ public class EditTextCaption extends EditTextBoldCursor { makeSelectedUnderline(); mode.finish(); return true; + } else if (item.getItemId() == R.id.menu_translate) { + makeSelectedTranslate(); + mode.finish(); + return true; } try { return callback.onActionItemClicked(mode, item); } catch (Exception ignore) { - } return true; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java index 3c269b1f6..48efd2fce 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java @@ -35,6 +35,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; +import org.jetbrains.annotations.NotNull; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; @@ -52,6 +53,7 @@ import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; +import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -67,10 +69,20 @@ import org.telegram.ui.Components.SizeNotifierFrameLayout; import java.util.ArrayList; import java.util.HashMap; +import java.util.Locale; +import java.util.concurrent.atomic.AtomicBoolean; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import kotlin.Unit; +import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.transtale.TranslateBottomSheet; +import tw.nekomimi.nekogram.transtale.TranslateDb; +import tw.nekomimi.nekogram.transtale.Translator; +import tw.nekomimi.nekogram.transtale.TranslatorKt; +import tw.nekomimi.nekogram.utils.AlertUtil; + public class PhotoAlbumPickerActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { public interface PhotoAlbumPickerActivityDelegate { @@ -179,7 +191,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati } ActionBarMenuItem menuItem = menu.addItem(0, R.drawable.ic_ab_other); menuItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); - menuItem.addSubItem(1, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)); + menuItem.addSubItem(1, R.drawable.baseline_open_in_browser_24, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)); sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context, SharedConfig.smoothKeyboard) { @@ -382,14 +394,14 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati writeButtonDrawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_dialogFloatingButton), Theme.getColor(Build.VERSION.SDK_INT >= 21 ? Theme.key_dialogFloatingButtonPressed : Theme.key_dialogFloatingButton)); 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)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.SRC_IN)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, writeButtonDrawable, 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56)); writeButtonDrawable = combinedDrawable; } writeButton.setBackgroundDrawable(writeButtonDrawable); writeButton.setImageResource(R.drawable.attach_send); - writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.MULTIPLY)); + writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.SRC_IN)); writeButton.setScaleType(ImageView.ScaleType.CENTER); if (Build.VERSION.SDK_INT >= 21) { writeButton.setOutlineProvider(new ViewOutlineProvider() { @@ -450,38 +462,66 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati sendPopupLayout.setShowedFromBotton(false); itemCells = new ActionBarMenuSubItem[2]; - for (int a = 0; a < 2; a++) { - if (a == 1 && UserObject.isUserSelf(user)) { + for (int a = 0; a < 3; a++) { + if (a == 2 && UserObject.isUserSelf(user)) { continue; } int num = a; itemCells[a] = new ActionBarMenuSubItem(getParentActivity()); if (num == 0) { - if (UserObject.isUserSelf(user)) { - itemCells[a].setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.msg_schedule); - } else { - itemCells[a].setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); - } + itemCells[a].setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate); } else if (num == 1) { + if (UserObject.isUserSelf(user)) { + itemCells[a].setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.baseline_date_range_24); + } else { + itemCells[a].setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.baseline_date_range_24); + } + } else if (num == 2) { itemCells[a].setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); } itemCells[a].setMinimumWidth(AndroidUtilities.dp(196)); sendPopupLayout.addView(itemCells[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * a, 0, 0)); + + int chatId; + if (chat != null) { + chatId = chat.id; + } else if (user != null) { + chatId = user.id; + } else { + chatId = -1; + } + itemCells[a].setOnClickListener(v -> { if (sendPopupWindow != null && sendPopupWindow.isShowing()) { sendPopupWindow.dismiss(); } if (num == 0) { + translateComment(TranslateDb.getChatLanguage(chatId, TranslatorKt.getCode2Locale(NekoConfig.translateInputLang))); + } else if (num == 1) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), chatActivity.getDialogId(), (notify, scheduleDate) -> { sendSelectedPhotos(selectedPhotos, selectedPhotosOrder, notify, scheduleDate); finishFragment(); }); - } else if (num == 1) { + } else if (num == 2) { sendSelectedPhotos(selectedPhotos, selectedPhotosOrder, true, 0); finishFragment(); } }); + itemCells[a].setOnLongClickListener(v -> { + if (num == 0) { + Translator.showTargetLangSelect(itemCells[num], true, (locale) -> { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + translateComment(locale); + TranslateDb.saveChatLanguage(chatId, locale); + return Unit.INSTANCE; + }); + return true; + } + return false; + }); } sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); @@ -548,6 +588,59 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati return fragmentView; } + private void translateComment(Locale target) { + + if (NekoConfig.translationProvider < 0) { + TranslateBottomSheet.show(getParentActivity(), commentTextView.getText().toString()); + } else { + + TranslateDb db = TranslateDb.forLocale(target); + String origin = commentTextView.getText().toString(); + + if (db.contains(origin)) { + + String translated = db.query(origin); + commentTextView.getEditText().setText(translated); + + return; + + } + + Translator.translate(target, origin, new Translator.Companion.TranslateCallBack() { + + final AtomicBoolean cancel = new AtomicBoolean(); + AlertDialog status = AlertUtil.showProgress(getParentActivity()); + + { + + status.setOnCancelListener((__) -> { + cancel.set(true); + }); + + status.show(); + + } + + @Override public void onSuccess(@NotNull String translation) { + status.dismiss(); + commentTextView.getEditText().setText(translation); + } + + @Override public void onFailed(boolean unsupported, @NotNull String message) { + status.dismiss(); + AlertUtil.showTransFailedDialog(getParentActivity(), unsupported, message, () -> { + status = AlertUtil.showProgress(getParentActivity()); + status.show(); + Translator.translate(origin, this); + }); + } + + }); + + } + + } + @Override public void onResume() { super.onResume(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index 7dc9ceb33..7a9762a43 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -45,6 +45,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; +import org.jetbrains.annotations.NotNull; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; @@ -91,10 +92,20 @@ import org.telegram.ui.Components.SizeNotifierFrameLayout; import java.util.ArrayList; import java.util.HashMap; +import java.util.Locale; +import java.util.concurrent.atomic.AtomicBoolean; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import kotlin.Unit; +import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.transtale.TranslateBottomSheet; +import tw.nekomimi.nekogram.transtale.TranslateDb; +import tw.nekomimi.nekogram.transtale.Translator; +import tw.nekomimi.nekogram.transtale.TranslatorKt; +import tw.nekomimi.nekogram.utils.AlertUtil; + public class PhotoPickerActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { public interface PhotoPickerActivityDelegate { @@ -504,7 +515,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } }); showAsListItem = menuItem.addSubItem(change_sort, R.drawable.msg_list, LocaleController.getString("ShowAsList", R.string.ShowAsList)); - menuItem.addSubItem(open_in, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)); + menuItem.addSubItem(open_in, R.drawable.baseline_open_in_browser_24, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)); } if (selectedAlbum == null) { @@ -978,14 +989,14 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen writeButtonDrawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_dialogFloatingButton), Theme.getColor(Build.VERSION.SDK_INT >= 21 ? Theme.key_dialogFloatingButtonPressed : Theme.key_dialogFloatingButton)); 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)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.SRC_IN)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, writeButtonDrawable, 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56)); writeButtonDrawable = combinedDrawable; } writeButton.setBackgroundDrawable(writeButtonDrawable); writeButton.setImageResource(R.drawable.attach_send); - writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.MULTIPLY)); + writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.SRC_IN)); writeButton.setScaleType(ImageView.ScaleType.CENTER); if (Build.VERSION.SDK_INT >= 21) { writeButton.setOutlineProvider(new ViewOutlineProvider() { @@ -1042,34 +1053,60 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen sendPopupLayout.setShowedFromBotton(false); itemCells = new ActionBarMenuSubItem[2]; - for (int a = 0; a < 2; a++) { - if (a == 1 && UserObject.isUserSelf(user)) { + for (int a = 0; a < 3; a++) { + if (a == 2 && UserObject.isUserSelf(user)) { continue; } int num = a; itemCells[a] = new ActionBarMenuSubItem(getParentActivity()); if (num == 0) { - if (UserObject.isUserSelf(user)) { - itemCells[a].setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.msg_schedule); - } else { - itemCells[a].setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); - } + itemCells[a].setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate); } else if (num == 1) { + if (UserObject.isUserSelf(user)) { + itemCells[a].setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.baseline_date_range_24); + } else { + itemCells[a].setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.baseline_date_range_24); + } + } else if (num == 2) { itemCells[a].setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); } itemCells[a].setMinimumWidth(AndroidUtilities.dp(196)); sendPopupLayout.addView(itemCells[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * a, 0, 0)); + int chatId; + if (chat != null) { + chatId = chat.id; + } else if (user != null) { + chatId = user.id; + } else { + chatId = -1; + } itemCells[a].setOnClickListener(v -> { if (sendPopupWindow != null && sendPopupWindow.isShowing()) { sendPopupWindow.dismiss(); } if (num == 0) { - AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), chatActivity.getDialogId(), this::sendSelectedPhotos); + translateComment(TranslateDb.getChatLanguage(chatId, TranslatorKt.getCode2Locale(NekoConfig.translateInputLang))); } else if (num == 1) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), chatActivity.getDialogId(), this::sendSelectedPhotos); + } else if (num == 2) { sendSelectedPhotos(true, 0); } }); + itemCells[a].setOnLongClickListener(v -> { + if (num == 0) { + Translator.showTargetLangSelect(itemCells[num], true, (locale) -> { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + translateComment(locale); + TranslateDb.saveChatLanguage(chatId, locale); + return Unit.INSTANCE; + }); + return true; + } + return false; + }); } sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); @@ -1133,6 +1170,59 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen return fragmentView; } + private void translateComment(Locale target) { + + if (NekoConfig.translationProvider < 0) { + TranslateBottomSheet.show(getParentActivity(), commentTextView.getText().toString()); + } else { + + TranslateDb db = TranslateDb.forLocale(target); + String origin = commentTextView.getText().toString(); + + if (db.contains(origin)) { + + String translated = db.query(origin); + commentTextView.getEditText().setText(translated); + + return; + + } + + Translator.translate(target, origin, new Translator.Companion.TranslateCallBack() { + + final AtomicBoolean cancel = new AtomicBoolean(); + AlertDialog status = AlertUtil.showProgress(getParentActivity()); + + { + + status.setOnCancelListener((__) -> { + cancel.set(true); + }); + + status.show(); + + } + + @Override public void onSuccess(@NotNull String translation) { + status.dismiss(); + commentTextView.getEditText().setText(translation); + } + + @Override public void onFailed(boolean unsupported, @NotNull String message) { + status.dismiss(); + AlertUtil.showTransFailedDialog(getParentActivity(), unsupported, message, () -> { + status = AlertUtil.showProgress(getParentActivity()); + status.show(); + Translator.translate(origin, this); + }); + } + + }); + + } + + } + @Override protected void onPanTranslationUpdate(int y) { if (listView == null) { @@ -1251,7 +1341,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen for (int a = 0, N = recentSearches.size(); a < N; a++) { editor.putString("recent" + a, recentSearches.get(a)); } - editor.commit(); + editor.apply(); } private void loadRecentSearch() { @@ -1869,9 +1959,9 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen case 3: { TextCell cell = (TextCell) holder.itemView; if (position < recentSearches.size()) { - cell.setTextAndIcon(recentSearches.get(position), R.drawable.menu_recent, false); + cell.setTextAndIcon(recentSearches.get(position), R.drawable.baseline_schedule_24, false); } else { - cell.setTextAndIcon(LocaleController.getString("ClearRecentHistory", R.string.ClearRecentHistory), R.drawable.menu_clear_recent, false); + cell.setTextAndIcon(LocaleController.getString("ClearRecentHistory", R.string.ClearRecentHistory), R.drawable.baseline_delete_sweep_24, false); } break; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 64e2aff75..8fd3258e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -44,22 +44,6 @@ import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.provider.Settings; -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.collection.ArrayMap; -import androidx.core.content.ContextCompat; -import androidx.core.content.FileProvider; -import androidx.core.view.ViewCompat; -import androidx.core.widget.NestedScrollView; -import androidx.dynamicanimation.animation.DynamicAnimation; -import androidx.dynamicanimation.animation.SpringAnimation; -import androidx.dynamicanimation.animation.SpringForce; -import androidx.recyclerview.widget.DefaultItemAnimator; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.LinearSmoothScrollerEnd; -import androidx.recyclerview.widget.RecyclerView; - import android.text.Layout; import android.text.Selection; import android.text.Spannable; @@ -112,11 +96,29 @@ import android.widget.Scroller; import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.Keep; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.collection.ArrayMap; +import androidx.core.content.ContextCompat; +import androidx.core.content.FileProvider; +import androidx.core.view.ViewCompat; +import androidx.core.widget.NestedScrollView; +import androidx.dynamicanimation.animation.DynamicAnimation; +import androidx.dynamicanimation.animation.SpringAnimation; +import androidx.dynamicanimation.animation.SpringForce; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScrollerEnd; +import androidx.recyclerview.widget.RecyclerView; + import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; +import org.jetbrains.annotations.NotNull; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.Bitmaps; import org.telegram.messenger.BringAppForegroundService; import org.telegram.messenger.BuildConfig; @@ -124,31 +126,34 @@ import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DownloadController; -import org.telegram.messenger.MediaDataController; import org.telegram.messenger.Emoji; +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.LocaleController; +import org.telegram.messenger.MediaController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; import org.telegram.messenger.SecureDocument; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; +import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; import org.telegram.messenger.WebFile; -import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.FileLoader; -import org.telegram.messenger.FileLog; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.MediaController; -import org.telegram.messenger.MessagesController; -import org.telegram.messenger.NotificationCenter; -import org.telegram.messenger.R; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; -import org.telegram.messenger.UserConfig; -import org.telegram.messenger.MessageObject; -import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.ActionBarMenu; +import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AlertDialog; @@ -156,9 +161,6 @@ import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Adapters.MentionsAdapter; -import org.telegram.ui.ActionBar.ActionBar; -import org.telegram.ui.ActionBar.ActionBarMenu; -import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.PhotoPickerPhotoCell; import org.telegram.ui.Components.AlertsCreator; @@ -168,7 +170,6 @@ import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.ChatAttachAlert; import org.telegram.ui.Components.CheckBox; import org.telegram.ui.Components.ClippingImageView; -import org.telegram.messenger.ImageReceiver; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.FadingTextViewLayout; import org.telegram.ui.Components.FilterShaders; @@ -211,8 +212,17 @@ import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import kotlin.Unit; import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.NekoXConfig; +import tw.nekomimi.nekogram.transtale.TranslateBottomSheet; +import tw.nekomimi.nekogram.transtale.TranslateDb; +import tw.nekomimi.nekogram.transtale.Translator; +import tw.nekomimi.nekogram.transtale.TranslatorKt; +import tw.nekomimi.nekogram.utils.AlertUtil; +import tw.nekomimi.nekogram.utils.ProxyUtil; @SuppressWarnings("unchecked") public class PhotoViewer implements NotificationCenter.NotificationCenterDelegate, GestureDetector2.OnGestureListener, GestureDetector2.OnDoubleTapListener { @@ -414,7 +424,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private int keyboardSize; private int currentPanTranslationY; - + public final static int SELECT_TYPE_AVATAR = 1; public final static int SELECT_TYPE_WALLPAPER = 3; public final static int SELECT_TYPE_QR = 10; @@ -596,7 +606,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat lastSaveTime = SystemClock.elapsedRealtime(); Utilities.globalQueue.postRunnable(() -> { SharedPreferences.Editor editor = ApplicationLoader.applicationContext.getSharedPreferences("media_saved_pos", Activity.MODE_PRIVATE).edit(); - editor.putFloat(shouldSavePositionForCurrentVideo, value).commit(); + editor.putFloat(shouldSavePositionForCurrentVideo, value).apply(); }); } } @@ -823,9 +833,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private boolean bottomTouchEnabled = true; private ArrayList imagesArrTemp = new ArrayList<>(); - private SparseArray[] imagesByIdsTemp = new SparseArray[] {new SparseArray<>(), new SparseArray<>()}; + private SparseArray[] imagesByIdsTemp = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private ArrayList imagesArr = new ArrayList<>(); - private SparseArray[] imagesByIds = new SparseArray[] {new SparseArray<>(), new SparseArray<>()}; + private SparseArray[] imagesByIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private ArrayList imagesArrLocations = new ArrayList<>(); private ArrayList secureDocuments = new ArrayList<>(); private ArrayList avatarsArr = new ArrayList<>(); @@ -836,6 +846,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private android.graphics.Rect hitRect = new android.graphics.Rect(); private final static int gallery_menu_save = 1; + private final static int gallery_menu_scan = 8; private final static int gallery_menu_showall = 2; private final static int gallery_menu_send = 3; private final static int gallery_menu_send_noquote = 93; @@ -847,8 +858,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private final static int gallery_menu_openin = 11; private final static int gallery_menu_masks = 13; private final static int gallery_menu_savegif = 14; - private final static int gallery_menu_setascurrent = 94; private final static int gallery_menu_masks2 = 15; + private final static int gallery_menu_setascurrent = 94; private static DecelerateInterpolator decelerateInterpolator; private static Paint progressPaint; @@ -2640,7 +2651,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat String finalPath = (String) args[1]; long finalSize = (Long) args[3]; float progress = (float) args[4]; - photoProgressViews[0].setProgress(progress,true); + photoProgressViews[0].setProgress(progress, true); if (finalSize != 0) { requestingPreview = false; photoProgressViews[0].setProgress(1f, true); @@ -2653,7 +2664,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private void showDownloadAlert() { AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); boolean alreadyDownloading = currentMessageObject != null && currentMessageObject.isVideo() && FileLoader.getInstance(currentMessageObject.currentAccount).isLoadingFile(currentFileNames[0]); if (alreadyDownloading) { @@ -2664,6 +2675,55 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat showAlertDialog(builder); } + private void onScanPressed() { + if (parentActivity == null) { + return; + } + try { + File f = null; + boolean isVideo = false; + + if (currentMessageObject != null) { + isVideo = currentMessageObject.isVideo(); + /*if (currentMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) { + AndroidUtilities.openUrl(parentActivity, currentMessageObject.messageOwner.media.webpage.url); + return; + }*/ + if (!TextUtils.isEmpty(currentMessageObject.messageOwner.attachPath)) { + f = new File(currentMessageObject.messageOwner.attachPath); + if (!f.exists()) { + f = null; + } + } + if (f == null) { + f = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + } + } else if (currentFileLocation != null) { + f = FileLoader.getPathToAttach(currentFileLocation.location, avatarsDialogId != 0 || isEvent); + } + + Bitmap bitmap; + + if (isVideo) { + + bitmap = videoTextureView.getBitmap(); + + } else if (f != null && f.exists()) { + + bitmap = ImageLoader.loadBitmap(f.getPath(), null, -1f, -1f, false); + + } else { + showDownloadAlert(); + return; + } + + ProxyUtil.tryReadQR(parentActivity, bitmap); + + } catch (Exception ignored) { + AlertUtil.showToast(LocaleController.getString("NoQrFound", R.string.NoQrFound)); + } + } + private void onSharePressed() { if (parentActivity == null || !allowShare) { return; @@ -2757,7 +2817,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat final Drawable circleDrawable = ContextCompat.getDrawable(parentActivity, R.drawable.circle_big); final CombinedDrawable playDrawable = new CombinedDrawable(circleDrawable.mutate(), ContextCompat.getDrawable(parentActivity, R.drawable.video_play1)); final CombinedDrawable pauseDrawable = new CombinedDrawable(circleDrawable.mutate(), ContextCompat.getDrawable(parentActivity, R.drawable.video_pause1)); - progressDrawables = new Drawable[] { + progressDrawables = new Drawable[]{ circleDrawable, // PROGRESS_EMPTY ContextCompat.getDrawable(parentActivity, R.drawable.cancel_big), // PROGRESS_CANCEL ContextCompat.getDrawable(parentActivity, R.drawable.load_big), // PROGRESS_LOAD @@ -3038,6 +3098,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else { showDownloadAlert(); } + } else if (id == gallery_menu_scan) { + onScanPressed(); } else if (id == gallery_menu_showall) { if (currentDialogId != 0) { disableShowCheck = true; @@ -3416,24 +3478,27 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ActionBarMenu menu = actionBar.createMenu(); - masksItem = menu.addItem(gallery_menu_masks, R.drawable.msg_mask); + masksItem = menu.addItem(gallery_menu_masks, R.drawable.deproko_baseline_masks_24); pipItem = menu.addItem(gallery_menu_pip, R.drawable.ic_goinline); sendNoQuoteItem = menu.addItem(gallery_menu_send_noquote, R.drawable.msg_forward_noquote); sendItem = menu.addItem(gallery_menu_send, R.drawable.msg_forward); menuItem = menu.addItem(0, R.drawable.ic_ab_other); - menuItem.addSubItem(gallery_menu_openin, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_openin, R.drawable.baseline_open_in_browser_24, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)).setColors(0xfffafafa, 0xfffafafa); menuItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); allMediaItem = menuItem.addSubItem(gallery_menu_showall, R.drawable.msg_media, LocaleController.getString("ShowAllMedia", R.string.ShowAllMedia)); allMediaItem.setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_savegif, R.drawable.msg_gif, LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_savegif, R.drawable.deproko_baseline_gif_24, LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)).setColors(0xfffafafa, 0xfffafafa); menuItem.addSubItem(gallery_menu_showinchat, R.drawable.msg_message, LocaleController.getString("ShowInChat", R.string.ShowInChat)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_masks2, R.drawable.msg_sticker, LocaleController.getString("ShowStickers", R.string.ShowStickers)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_share, R.drawable.msg_shareout, LocaleController.getString("ShareFile", R.string.ShareFile)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_save, R.drawable.msg_gallery, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_setascurrent, R.drawable.menu_camera, LocaleController.getString("SetAsCurrent", R.string.SetAsCurrent)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_delete, R.drawable.msg_delete, LocaleController.getString("Delete", R.string.Delete)).setColors(0xfffafafa, 0xfffafafa); - menuItem.addSubItem(gallery_menu_cancel_loading, R.drawable.msg_cancel, LocaleController.getString("StopDownload", R.string.StopDownload)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_masks2, R.drawable.deproko_baseline_stickers_filled_24, LocaleController.getString("ShowStickers", R.string.ShowStickers)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_share, R.drawable.baseline_share_24, LocaleController.getString("ShareFile", R.string.ShareFile)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_save, R.drawable.baseline_image_24, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)).setColors(0xfffafafa, 0xfffafafa); + + menuItem.addSubItem(gallery_menu_scan, R.drawable.wallet_qr, LocaleController.getString("ScanQRCode", R.string.ScanQRCode)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_setascurrent, R.drawable.deproko_baseline_camera_26, LocaleController.getString("SetAsCurrent", R.string.SetAsCurrent)).setColors(0xfffafafa, 0xfffafafa); + + menuItem.addSubItem(gallery_menu_delete, R.drawable.baseline_delete_24, LocaleController.getString("Delete", R.string.Delete)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_cancel_loading, R.drawable.baseline_cancel_24, LocaleController.getString("StopDownload", R.string.StopDownload)).setColors(0xfffafafa, 0xfffafafa); menuItem.redrawPopup(0xf9222222); sendNoQuoteItem.setContentDescription(LocaleController.getString("NoQuoteForward", R.string.NoQuoteForward)); sendItem.setContentDescription(LocaleController.getString("Forward", R.string.Forward)); @@ -3458,9 +3523,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat bottomLayout.setBackgroundColor(0x7f000000); containerView.addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT)); - pressedDrawable[0] = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, new int[] {0x32000000, 0}); + pressedDrawable[0] = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, new int[]{0x32000000, 0}); pressedDrawable[0].setShape(GradientDrawable.RECTANGLE); - pressedDrawable[1] = new GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, new int[] {0x32000000, 0}); + pressedDrawable[1] = new GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, new int[]{0x32000000, 0}); pressedDrawable[1].setShape(GradientDrawable.RECTANGLE); groupedPhotosListView = new GroupedPhotosListView(actvityContext, AndroidUtilities.dp(10)); @@ -3567,7 +3632,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat containerView.addView(miniProgressView, LayoutHelper.createFrame(64, 64, Gravity.CENTER)); shareButton = new ImageView(containerView.getContext()); - shareButton.setImageResource(R.drawable.share); + shareButton.setImageResource(R.drawable.baseline_share_24); + shareButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.SRC_IN)); shareButton.setScaleType(ImageView.ScaleType.CENTER); shareButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); bottomLayout.addView(shareButton, LayoutHelper.createFrame(50, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); @@ -3809,9 +3875,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat pickerViewSendButton.setScaleType(ImageView.ScaleType.CENTER); Drawable drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_dialogFloatingButton), Theme.getColor(Build.VERSION.SDK_INT >= 21 ? Theme.key_dialogFloatingButtonPressed : Theme.key_dialogFloatingButton)); pickerViewSendButton.setBackgroundDrawable(drawable); - pickerViewSendButton.setColorFilter(new PorterDuffColorFilter(0xffffffff, PorterDuff.Mode.MULTIPLY)); + pickerViewSendButton.setColorFilter(new PorterDuffColorFilter(0xffffffff, PorterDuff.Mode.SRC_IN)); pickerViewSendButton.setImageResource(R.drawable.attach_send); - pickerViewSendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.MULTIPLY)); + pickerViewSendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.SRC_IN)); containerView.addView(pickerViewSendButton, LayoutHelper.createFrame(56, 56, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 14, 14)); pickerViewSendButton.setContentDescription(LocaleController.getString("Send", R.string.Send)); pickerViewSendButton.setOnClickListener(v -> { @@ -3853,8 +3919,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat sendPopupLayout.setBackgroundColor(0xf9222222); int i = 0; - for (int a = 0; a < 2; a++) { - if (a == 0 && placeProvider != null && placeProvider.getSelectedPhotos() != null) { + for (int a = 0; a < 3; a++) { + if (a == 1 && placeProvider != null && placeProvider.getSelectedPhotos() != null) { HashMap hashMap = placeProvider.getSelectedPhotos(); boolean hasTtl = false; for (HashMap.Entry entry : hashMap.entrySet()) { @@ -3876,34 +3942,60 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (hasTtl) { continue; } - } else if (a == 1 && UserObject.isUserSelf(user)) { + } else if (a == 2 && UserObject.isUserSelf(user)) { continue; } int num = a; ActionBarMenuSubItem cell = new ActionBarMenuSubItem(parentActivity); cell.setBackgroundDrawable(Theme.createSelectorDrawable(0x24ffffff, 7)); if (num == 0) { - if (UserObject.isUserSelf(user)) { - cell.setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.msg_schedule); - } else { - cell.setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); - } + cell.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate); } else if (num == 1) { + if (UserObject.isUserSelf(user)) { + cell.setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.baseline_date_range_24); + } else { + cell.setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.baseline_date_range_24); + } + } else if (num == 2) { cell.setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); } cell.setMinimumWidth(AndroidUtilities.dp(196)); cell.setColors(0xffffffff, 0xffffffff); sendPopupLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * i, 0, 0)); + int chatId; + if (chat != null) { + chatId = chat.id; + } else if (user != null) { + chatId = user.id; + } else { + chatId = -1; + } cell.setOnClickListener(v -> { if (sendPopupWindow != null && sendPopupWindow.isShowing()) { sendPopupWindow.dismiss(); } if (num == 0) { + translateComment(TranslateDb.getChatLanguage(chatId, TranslatorKt.getCode2Locale(NekoConfig.translateInputLang))); + } else if (num == 1) { AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentChatActivity.getDialogId(), this::sendPressed); } else if (num == 1) { sendPressed(false, 0); } }); + cell.setOnLongClickListener(v -> { + if (num == 0) { + Translator.showTargetLangSelect(cell, true, (locale) -> { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + translateComment(locale); + TranslateDb.saveChatLanguage(chatId, locale); + return Unit.INSTANCE; + }); + return true; + } + return false; + }); i++; } @@ -4196,7 +4288,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat SharedPreferences preferences1 = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences1.edit(); editor.putInt("self_destruct", value); - editor.commit(); + editor.apply(); bottomSheet.dismiss(); int seconds; if (value >= 0 && value < 21) { @@ -4210,7 +4302,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else if (object1 instanceof MediaController.SearchImage) { ((MediaController.SearchImage) object1).ttl = seconds; } - timeItem.setColorFilter(seconds != 0 ? new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.MULTIPLY) : null); + timeItem.setColorFilter(seconds != 0 ? new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN) : null); if (!checkImageView.isChecked()) { checkImageView.callOnClick(); } @@ -4576,7 +4668,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat Object object = mentionsAdapter.getItem(position); if (object instanceof String) { AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setMessage(LocaleController.getString("ClearSearch", R.string.ClearSearch)); builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> mentionsAdapter.clearRecentHashtags()); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -4595,6 +4687,58 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private void translateComment(Locale target) { + + String origin = captionEditText.getFieldCharSequence().toString(); + + if (NekoConfig.translationProvider < 0) { + TranslateBottomSheet.show(parentActivity, origin); + } else { + + TranslateDb db = TranslateDb.forLocale(target); + if (db.contains(origin)) { + String translated = db.query(origin); + captionEditText.setFieldText(translated); + return; + + } + + Translator.translate(target, origin, new Translator.Companion.TranslateCallBack() { + + final AtomicBoolean cancel = new AtomicBoolean(); + AlertDialog status = AlertUtil.showProgress(parentActivity); + + { + + status.setOnCancelListener((__) -> { + cancel.set(true); + }); + + status.show(); + + } + + @Override public void onSuccess(@NotNull String translation) { + status.dismiss(); + captionEditText.setFieldText(translation); + } + + @Override public void onFailed(boolean unsupported, @NotNull String message) { + status.dismiss(); + AlertUtil.showTransFailedDialog(parentActivity, unsupported, message, () -> { + status = AlertUtil.showProgress(parentActivity); + status.show(); + Translator.translate(origin, this); + }); + } + + }); + + } + + } + + private void sendPressed(boolean notify, int scheduleDate) { if (captionEditText.getTag() != null) { return; @@ -4607,7 +4751,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat TLRPC.Chat chat = parentChatActivity.getCurrentChat(); TLRPC.User user = parentChatActivity.getCurrentUser(); if (user != null || ChatObject.isChannel(chat) && chat.megagroup || !ChatObject.isChannel(chat)) { - MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + parentChatActivity.getDialogId(), !notify).commit(); + MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + parentChatActivity.getDialogId(), !notify).apply(); } } VideoEditedInfo videoEditedInfo = getCurrentVideoEditedInfo(); @@ -4651,6 +4795,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } openCaptionEnter(); }; + private TextView createCaptionTextView() { TextView textView = new TextView(actvityContext) { @Override @@ -4685,12 +4830,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return 0; } - private int getRightInset() { - if (lastInsets != null && Build.VERSION.SDK_INT >= 21) { - return ((WindowInsets) lastInsets).getSystemWindowInsetRight(); - } - return 0; - } + private int getRightInset() { + if (lastInsets != null && Build.VERSION.SDK_INT >= 21) { + return ((WindowInsets) lastInsets).getSystemWindowInsetRight(); + } + return 0; + } private void dismissInternal() { try { @@ -4853,7 +4998,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat x = max; } videoPreviewFrame.setTranslationX(x); - } + } private void showVideoSeekPreviewPosition(boolean show) { if (show && videoPreviewFrame.getTag() != null || !show && videoPreviewFrame.getTag() == null) { @@ -5062,7 +5207,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat Object object = imagesArrLocals.get(currentIndex); if (apply) { CharSequence caption = captionEditText.getFieldCharSequence(); - CharSequence[] result = new CharSequence[] {caption}; + CharSequence[] result = new CharSequence[]{caption}; ArrayList entities = MediaDataController.getInstance(currentAccount).getEntities(result, supportsSendingNewEntities()); if (object instanceof MediaController.PhotoEntry) { @@ -5157,12 +5302,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat Drawable drawable = pickerViewSendButton.getBackground(); Theme.setSelectorDrawableColor(drawable, color, false); Theme.setSelectorDrawableColor(drawable, Theme.getColor(Build.VERSION.SDK_INT >= 21 ? Theme.key_dialogFloatingButtonPressed : Theme.key_dialogFloatingButton), true); - pickerViewSendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.MULTIPLY)); + pickerViewSendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.SRC_IN)); } if (checkImageView != null) { checkImageView.setColor(Theme.getColor(Theme.key_dialogFloatingButton), 0xffffffff); } - PorterDuffColorFilter filter = new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY); + PorterDuffColorFilter filter = new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN); if (timeItem != null && timeItem.getColorFilter() != null) { timeItem.setColorFilter(filter); } @@ -6109,13 +6254,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (currentEditMode == 1) { entry.isCropped = true; - cropItem.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.MULTIPLY)); + cropItem.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); } else if (currentEditMode == 2) { entry.isFiltered = true; - tuneItem.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.MULTIPLY)); + tuneItem.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); } else if (currentEditMode == 3) { entry.isPainted = true; - paintItem.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.MULTIPLY)); + paintItem.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); } if ((sendPhotoType == 0 || sendPhotoType == 4) && placeProvider != null) { @@ -6489,7 +6634,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); builder.setMessage(LocaleController.getString("DiscardChanges", R.string.DiscardChanges)); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> switchToEditMode(0)); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showAlertDialog(builder); @@ -7051,7 +7196,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat TLRPC.BotInlineResult botInlineResult = (TLRPC.BotInlineResult) object; if (botInlineResult.document != null) { return FileLoader.getAttachFileName(botInlineResult.document); - } else if (botInlineResult.photo != null) { + } else if (botInlineResult.photo != null) { TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(botInlineResult.photo.sizes, AndroidUtilities.getPhotoSize()); return FileLoader.getAttachFileName(sizeFull); } else if (botInlineResult.content instanceof TLRPC.TL_webDocument) { @@ -7731,6 +7876,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentAnimation != null) { menuItem.hideSubItem(gallery_menu_save); menuItem.hideSubItem(gallery_menu_share); + menuItem.hideSubItem(gallery_menu_scan); if (!newMessageObject.canDeleteMessage(parentChatActivity != null && parentChatActivity.isInScheduleMode(), null)) { menuItem.hideSubItem(gallery_menu_delete); } @@ -7793,10 +7939,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat allowShare = false; menuItem.hideSubItem(gallery_menu_save); shareButton.setVisibility(View.GONE); + menuItem.hideSubItem(gallery_menu_scan); menuItem.hideSubItem(gallery_menu_share); } else { allowShare = true; menuItem.showSubItem(gallery_menu_save); + menuItem.showSubItem(gallery_menu_scan); shareButton.setVisibility(!videoPlayerControlVisible ? View.VISIBLE : View.GONE); if (shareButton.getVisibility() == View.VISIBLE) { menuItem.hideSubItem(gallery_menu_share); @@ -7809,6 +7957,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else if (!secureDocuments.isEmpty()) { allowShare = false; menuItem.hideSubItem(gallery_menu_save); + menuItem.hideSubItem(gallery_menu_scan); nameTextView.setText(""); dateTextView.setText(""); actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, switchingToIndex + 1, secureDocuments.size())); @@ -7834,7 +7983,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat nameTextView.setText(""); } } - long date = (long) avatarsArr.get(switchingToIndex).date * 1000; + long date = (long) avatarsArr.get(switchingToIndex).date * 1000; if (date != 0) { String dateString = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.getInstance().formatterYear.format(new Date(date)), LocaleController.getInstance().formatterDay.format(new Date(date))); dateTextView.setText(dateString); @@ -7850,6 +7999,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, switchingToIndex + 1, imagesArrLocations.size())); } menuItem.showSubItem(gallery_menu_save); + menuItem.showSubItem(gallery_menu_scan); allowShare = true; shareButton.setVisibility(!videoPlayerControlVisible ? View.VISIBLE : View.GONE); if (shareButton.getVisibility() == View.VISIBLE) { @@ -8011,8 +8161,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } updateCaptionTextForCurrentPhoto(object); - PorterDuffColorFilter filter = new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.MULTIPLY); - timeItem.setColorFilter(ttl != 0 ? filter : null); + PorterDuffColorFilter filter = new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN); + timeItem.setColorFilter(ttl != 0 ? filter : null); paintItem.setColorFilter(isPainted ? filter : null); cropItem.setColorFilter(isCropped ? filter : null); tuneItem.setColorFilter(isFiltered ? filter : null); @@ -8070,9 +8220,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (sharedMediaType == MediaDataController.MEDIA_FILE) { if (canZoom = newMessageObject.canPreviewDocument()) { menuItem.showSubItem(gallery_menu_save); + menuItem.showSubItem(gallery_menu_scan); setDoubleTapEnabled(true); } else { menuItem.hideSubItem(gallery_menu_save); + menuItem.hideSubItem(gallery_menu_scan); setDoubleTapEnabled(false); } } @@ -9049,9 +9201,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animationStartTime = System.currentTimeMillis(); animateToX = getLeftInset() / 2 - getRightInset() / 2; if (currentEditMode == 2) { - animateToY = AndroidUtilities.dp(92)-AndroidUtilities.dp(24 + 32); + animateToY = AndroidUtilities.dp(92) - AndroidUtilities.dp(24 + 32); } else if (currentEditMode == 3) { - animateToY = AndroidUtilities.dp(44)-AndroidUtilities.dp(24 + 32); + animateToY = AndroidUtilities.dp(44) - AndroidUtilities.dp(24 + 32); } //animateToY = -AndroidUtilities.dp(24 + 32) + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight / 2 : 0); animateToScale = newScale / scaleFinal; @@ -9121,10 +9273,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else { windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; } - if (chatActivity != null && chatActivity.getCurrentEncryptedChat() != null) { + if (chatActivity != null && chatActivity.getCurrentEncryptedChat() != null && !NekoXConfig.disableFlagSecure) { windowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_SECURE; } else { - windowLayoutParams.flags &=~ WindowManager.LayoutParams.FLAG_SECURE; + windowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_SECURE; } windowLayoutParams.softInputMode = (useSmoothKeyboard ? WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN : WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) | WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; windowView.setFocusable(false); @@ -9253,7 +9405,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animatingImageViews[i].setLayoutParams(layoutParams); } - windowView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){ + windowView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { if (animatingImageViews.length > 1) { @@ -10863,7 +11015,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (uri == null) { if (download) { - if (currentMessageObject != null) { + if (currentMessageObject != null) { if (!FileLoader.getInstance(currentAccount).isLoadingFile(currentFileNames[0])) { FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, 1, 0); } else { @@ -11308,7 +11460,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat SharedPreferences preferences = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); editor.putInt("compress_video2", selectedCompression); - editor.commit(); + editor.apply(); updateWidthHeightBitrateForCompression(); updateVideoInfo(); if (request) { @@ -11388,7 +11540,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (request == 1) { if (resultHeight == originalHeight && resultWidth == originalWidth) { tryStartRequestPreviewOnFinish = false; - photoProgressViews[0].setProgress(0,photoProgressViews[0].backgroundState == 0 || photoProgressViews[0].previousBackgroundState == 0); + photoProgressViews[0].setProgress(0, photoProgressViews[0].backgroundState == 0 || photoProgressViews[0].previousBackgroundState == 0); photoProgressViews[0].setBackgroundState(PROGRESS_PLAY, false); if (!wasRequestingPreview) { preparePlayer(currentPlayingVideoFile, false, false, currentSavedFilterState); @@ -11436,7 +11588,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } requestingPreview = true; - photoProgressViews[0].setProgress(0,photoProgressViews[0].backgroundState == 0 || photoProgressViews[0].previousBackgroundState == 0); + photoProgressViews[0].setProgress(0, photoProgressViews[0].backgroundState == 0 || photoProgressViews[0].previousBackgroundState == 0); photoProgressViews[0].setBackgroundState(PROGRESS_EMPTY, false); } } else { diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/ArticleTrans.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/ArticleTrans.kt new file mode 100644 index 000000000..cef27fa59 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/ArticleTrans.kt @@ -0,0 +1,202 @@ +package tw.nekomimi.nekogram.parts + +import kotlinx.coroutines.* +import org.telegram.messenger.LocaleController +import org.telegram.messenger.R +import org.telegram.tgnet.TLRPC +import org.telegram.ui.ArticleViewer +import tw.nekomimi.nekogram.NekoConfig +import tw.nekomimi.nekogram.transtale.TranslateDb +import tw.nekomimi.nekogram.transtale.Translator +import tw.nekomimi.nekogram.utils.AlertUtil +import tw.nekomimi.nekogram.utils.UIUtil +import java.lang.Runnable +import java.util.* +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger +import kotlin.collections.HashMap +import kotlin.collections.HashSet + +fun HashSet.filterBaseTexts(): HashSet { + + var hasNext: Boolean + + do { + + hasNext = false + + HashSet(this).forEach { item -> + + when (item) { + + is TLRPC.TL_textConcat -> { + + remove(item) + addAll(item.texts) + + hasNext = true + + } + + } + + } + + } while (hasNext) + + return this + +} + +fun ArticleViewer.doTransLATE() { + + if (NekoConfig.translationProvider < 0) { + + adapter[0].trans = false + transMenu.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate) + + AlertUtil.showTransFailedDialog(parentActivity,true,true,LocaleController.getString("InstantViewTransWithWeb",R.string.InstantViewTransWithWeb), Runnable { + + adapter[0].trans = true + transMenu.setTextAndIcon(LocaleController.getString("UndoTranslate", R.string.UndoTranslate), R.drawable.ic_translate) + + doTransLATE() + + }) + + return + + } + + val dialog = AlertUtil.showProgress(parentActivity) + + dialog.show() + + fun update(message: String) { + + UIUtil.runOnUIThread(Runnable { dialog.setMessage(message) }) + + } + + val transPool = newFixedThreadPoolContext(5, "Article Trans Pool") + + val cancel = AtomicBoolean(false) + + dialog.setOnCancelListener { + + adapter[0].trans = false + transMenu.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate) + cancel.set(true) + transPool.close() + + } + + GlobalScope.launch(Dispatchers.IO) { + + val copy = HashMap(adapter[0].textToBlocks) + val array = HashSet(adapter[0].textBlocks).filterBaseTexts() + + val errorCount = AtomicInteger() + + val deferreds = LinkedList>() + + val all = array.size + val taskCount = AtomicInteger(array.size) + + update("0 / $all") + + array.forEach { item -> + + when (item) { + + is TLRPC.RichText -> getText(adapter[0], null, item, item, copy[item] ?: copy[item.parentRichText], 1000, true).takeIf { it.isNotBlank() }?.toString() + is String -> item + else -> null + + }?.also { str -> + + deferreds.add(async(transPool) { + + if (TranslateDb.currentTarget().contains(str)) { + + update("${all - taskCount.get()} / $all") + + if (taskCount.decrementAndGet() % 10 == 0) UIUtil.runOnUIThread(Runnable { + + updatePaintSize() + + }) + + return@async + + } + + runCatching { + + if (cancel.get()) return@async + + Translator.translate(str) + + update((all - taskCount.get()).toString() + " / " + all) + + if (taskCount.decrementAndGet() % 10 == 0) UIUtil.runOnUIThread(Runnable { + + updatePaintSize() + + }) + + }.onFailure { + + if (cancel.get()) return@async + + if (errorCount.incrementAndGet() > 3) { + + cancel.set(true) + + UIUtil.runOnUIThread(Runnable { + + cancel.set(true) + dialog.dismiss() + updatePaintSize() + adapter[0].trans = false + transMenu.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate) + + AlertUtil.showTransFailedDialog(parentActivity, it is UnsupportedOperationException, true,it.message ?: it.javaClass.simpleName, Runnable { + doTransLATE() + }) + + }) + + } + + } + + }) + + }.also { + + if (it == null) taskCount.decrementAndGet() + + } + + } + + deferreds.awaitAll() + + UIUtil.runOnUIThread(Runnable { + + transPool.cancel() + + if (!cancel.get()) { + + updatePaintSize() + dialog.dismiss() + + } + + }) + + } + + +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/MessageTrans.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/MessageTrans.kt new file mode 100644 index 000000000..e5327a4e6 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/MessageTrans.kt @@ -0,0 +1,328 @@ +package tw.nekomimi.nekogram.parts + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.telegram.messenger.LocaleController +import org.telegram.messenger.MessageObject +import org.telegram.tgnet.TLRPC +import org.telegram.ui.Cells.ChatMessageCell +import org.telegram.ui.ChatActivity +import tw.nekomimi.nekogram.MessageHelper +import tw.nekomimi.nekogram.NekoConfig +import tw.nekomimi.nekogram.transtale.TranslateBottomSheet +import tw.nekomimi.nekogram.transtale.TranslateDb +import tw.nekomimi.nekogram.transtale.Translator +import tw.nekomimi.nekogram.transtale.code2Locale +import tw.nekomimi.nekogram.utils.AlertUtil +import tw.nekomimi.nekogram.utils.uDismiss +import java.util.* +import java.util.concurrent.atomic.AtomicBoolean + +fun MessageObject.toRawString(): String { + + var content: String + + if (messageOwner.media is TLRPC.TL_messageMediaPoll) { + + val poll = (messageOwner.media as TLRPC.TL_messageMediaPoll).poll + content = poll.question + content += "\n" + + for (answer in poll.answers) { + + content += "\n- " + content += answer.text + + } + + } else { + + content = messageOwner.message ?: "" + + } + + return content + +} + +fun MessageObject.translateFinished(locale: Locale): Boolean { + + val db = TranslateDb.forLocale(locale) + + if (isPoll) { + + val pool = (messageOwner.media as TLRPC.TL_messageMediaPoll).poll + + val question = db.query(pool.question) ?: return false + + pool.translatedQuestion = pool.question + "\n\n--------\n\n" + question + + pool.answers.forEach { + + val answer = db.query(it.text) ?: return false + + it.translatedText = it.text + " | " + answer + + } + + } else { + + val text = db.query(messageOwner.message) ?: return false + + messageOwner.translatedMessage = messageOwner.message + "\n\n--------\n\n" + text + + } + + return true + +} + +@JvmOverloads +fun ChatActivity.translateMessages(messages: Array, target: Locale = NekoConfig.translateToLang?.code2Locale ?: LocaleController.getInstance().currentLocale) { + + if (messages.all { it.messageOwner.translated }) { + + messages.forEach { messageObject -> + + messageObject.messageOwner.translated = false + + MessageHelper.resetMessageContent(messageObject); + + for (index in 0 until chatListView.childCount) { + + val cell = chatListView.getChildAt(index) + .takeIf { it is ChatMessageCell && it.messageObject === messageObject } as ChatMessageCell? + + if (cell != null) { + + MessageHelper.resetMessageContent(cell); + + break + + } + + } + + chatAdapter.updateRowWithMessageObject(messageObject, true) + + } + + return + + } + + if (NekoConfig.translationProvider < 0) { + + TranslateBottomSheet.show(parentActivity, messages.map { it.toRawString() }.filter { it.isNotBlank() }.joinToString("\n")) + + return + + } + + val status = AlertUtil.showProgress(parentActivity) + + val canceled = AtomicBoolean() + + status.setOnCancelListener { + + canceled.set(true) + + } + + status.show() + + GlobalScope.launch(Dispatchers.IO) { + + messages.forEachIndexed { i, selectedObject -> + + val isEnd = i == messages.size - 1 + + var messageCell: ChatMessageCell? = null + + for (index in 0 until chatListView.childCount) { + + val cell = chatListView.getChildAt(index) + .takeIf { it is ChatMessageCell && it.messageObject === selectedObject } as ChatMessageCell? + + if (cell != null) { + + messageCell = cell + + break + + } + + } + + if (selectedObject.translateFinished(target)) { + + withContext(Dispatchers.Main) { + + selectedObject.messageOwner.translated = true + + MessageHelper.resetMessageContent(selectedObject) + + messageCell?.also { + + MessageHelper.resetMessageContent(it) + + } + + chatAdapter.updateRowWithMessageObject(selectedObject, true) + + if (isEnd) status.dismiss() + + } + + return@forEachIndexed + + } + + withContext(Dispatchers.IO) trans@{ + + val db = TranslateDb.forLocale(target) + + if (selectedObject.isPoll) { + + val pool = (selectedObject.messageOwner.media as TLRPC.TL_messageMediaPoll).poll + + var question = db.query(pool.question) + + if (question == null) { + + if (canceled.get()) return@trans + + runCatching { + + question = Translator.translate(target, pool.question) + + }.onFailure { + + status.uDismiss() + + val parentActivity = parentActivity + + if (parentActivity != null && !canceled.get()) { + + AlertUtil.showTransFailedDialog(parentActivity, it is UnsupportedOperationException, false, it.message ?: it.javaClass.simpleName, Runnable { + + translateMessages(messages, target) + + }) + + } + + return@trans + + } + + } + + pool.translatedQuestion = pool.question + "\n\n--------\n\n" + question + + pool.answers.forEach { + + var answer = db.query(it.text) + + if (answer == null) { + + if (canceled.get()) return@trans + + runCatching { + + answer = Translator.translate(target, it.text) + + }.onFailure { e -> + + status.uDismiss() + + val parentActivity = parentActivity + + if (parentActivity != null && !canceled.get()) { + + AlertUtil.showTransFailedDialog(parentActivity, e is UnsupportedOperationException, false, e.message ?: e.javaClass.simpleName, Runnable { + + translateMessages(messages, target) + + }) + + } + + return@trans + + } + + } + + it.translatedText = answer + " | " + it.text + + } + + } else { + + var text = db.query(selectedObject.messageOwner.message) + + if (text == null) { + + runCatching { + + text = Translator.translate(target, selectedObject.messageOwner.message) + + }.onFailure { + + status.uDismiss() + + val parentActivity = parentActivity + + if (parentActivity != null && !canceled.get()) { + + AlertUtil.showTransFailedDialog(parentActivity, it is UnsupportedOperationException, false, it.message ?: it.javaClass.simpleName, Runnable { + + translateMessages(messages, target) + + }) + + } + + return@trans + + } + + + } + + selectedObject.messageOwner.translatedMessage = selectedObject.messageOwner.message + "\n\n--------\n\n" + text + + } + + if (!canceled.get()) { + + selectedObject.messageOwner.translated = true + + withContext(Dispatchers.Main) { + + MessageHelper.resetMessageContent(selectedObject) + + messageCell?.also { + + MessageHelper.resetMessageContent(it) + + } + + chatAdapter.updateRowWithMessageObject(selectedObject, true) + + if (isEnd) status.dismiss() + + } + + } else return@trans + + } + + } + + } + +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/ChatLanguage.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/ChatLanguage.java new file mode 100644 index 000000000..27c662ba7 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/ChatLanguage.java @@ -0,0 +1,37 @@ +package tw.nekomimi.nekogram.transtale; + +import org.dizitart.no2.Document; +import org.dizitart.no2.mapper.Mappable; +import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.objects.Id; +import org.dizitart.no2.objects.Index; + +@Index("chatId") +public class ChatLanguage implements Mappable { + + @Id + public int chatId; + + public String language; + + public ChatLanguage() { + } + + public ChatLanguage(int chatId, String language) { + this.chatId = chatId; + this.language = language; + } + + @Override public Document write(NitriteMapper mapper) { + Document document = new Document(); + document.put("chatId",chatId); + document.put("language",language); + return document; + } + + @Override public void read(NitriteMapper mapper, Document document) { + chatId = ((int) document.get("chatId")); + language = ((String) document.get("language")); + } + +} diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TransItem.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TransItem.java new file mode 100644 index 000000000..228bf4b14 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TransItem.java @@ -0,0 +1,40 @@ +package tw.nekomimi.nekogram.transtale; + +import org.dizitart.no2.Document; +import org.dizitart.no2.IndexType; +import org.dizitart.no2.mapper.Mappable; +import org.dizitart.no2.mapper.NitriteMapper; +import org.dizitart.no2.objects.Id; +import org.dizitart.no2.objects.Index; +import org.dizitart.no2.objects.Indices; + +@Index(value = "text") +public class TransItem implements Mappable { + + @Id + public String text; + public String trans; + + public TransItem() { + } + + public TransItem(String text, String trans) { + this.text = text; + this.trans = trans; + } + + @Override + public Document write(NitriteMapper mapper) { + Document document = new Document(); + document.put("text",text); + document.put("trans", trans); + return document; + } + + @Override + public void read(NitriteMapper mapper, Document document) { + text = (String) document.get("text"); + trans = (String) document.get("trans"); + } + +} diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TransUtils.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TransUtils.java new file mode 100644 index 000000000..fc66c9dce --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TransUtils.java @@ -0,0 +1,80 @@ +package tw.nekomimi.nekogram.transtale; + +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Bin + */ +public class TransUtils { + + public static String signWeb(String text, long key1, long key2) { + List c = new ArrayList<>(); + for (int F = 0; F < text.length(); F++) { + int p = text.charAt(F); + if (128 > p) { + c.add(p); + } else { + if (2048 > p) { + c.add(p >> 6 | 192); + } else { + if ((55296 == (64512 & p) && F + 1 < text.length() && 56320 == (64512 & text.charAt(F + 1)))) { + p = 65536 + ((1023 & p) << 10) + (1023 & text.charAt(++F)); + c.add(p >> 18 | 240); + c.add(p >> 12 & 63 | 128); + } else { + c.add(p >> 12 | 224); + } + c.add(p >> 6 & 63 | 128); + } + c.add(63 & p | 128); + } + } + String formula1 = "+-a^+6"; + String formula2 = "+-3^+b+-f"; + long v = key1; + for (Integer i : c) { + v += i; + v = n(v, formula1); + } + v = n(v, formula2); + v ^= key2; + if (0 > v) + v = (0x7fffffff & v) + 0x80000000L; + v %= 1e6; + return v + "." + (v ^ key1); + } + + private static long n(long r, String o) { + for (int t = 0; t < o.length() - 2; t += 3) { + long e = o.charAt(t + 2); + e = e >= 'a' ? e - 87 : e - '0'; + e = '+' == o.charAt(t + 1) ? r >>> e : r << e; + r = '+' == o.charAt(t) ? r + e & 0xffffffffL : r ^ e; + } + return r; + } + + public static String encodeURIComponent(String str) { + if (str == null) return null; + + byte[] bytes = str.getBytes(Charset.defaultCharset()); + StringBuilder builder = new StringBuilder(bytes.length); + + for (byte c : bytes) { + String HEX = "0123456789ABCDEF"; + if (c >= 'a' ? c <= 'z' || c == '~' : + c >= 'A' ? c <= 'Z' || c == '_' : + c >= '0' ? c <= '9' : c == '-' || c == '.') + builder.append((char) c); + else + builder.append('%') + .append(HEX.charAt(c >> 4 & 0xf)) + .append(HEX.charAt(c & 0xf)); + } + + return builder.toString(); + } + +} diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TranslateBottomSheet.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TranslateBottomSheet.java new file mode 100644 index 000000000..48efd6b57 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TranslateBottomSheet.java @@ -0,0 +1,211 @@ +package tw.nekomimi.nekogram.transtale; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.os.Build; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.CookieManager; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.browser.Browser; +import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RadialProgressView; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +import tw.nekomimi.nekogram.NekoConfig; + +public class TranslateBottomSheet extends BottomSheet { + + @SuppressLint("StaticFieldLeak") + private static TranslateBottomSheet instance; + private WebView webView; + private RadialProgressView progressBar; + private Activity parentActivity; + private FrameLayout containerLayout; + private String url; + + @SuppressLint("SetJavaScriptEnabled") + protected TranslateBottomSheet(Context context, final String text) { + super(context, false); + setApplyTopPadding(false); + setApplyBottomPadding(false); + setCanDismissWithSwipe(false); + + if (context instanceof Activity) { + parentActivity = (Activity) context; + } + + try { + switch (NekoConfig.translationProvider) { + case -1: + url = String.format("https://translate.google.com/?view=home&op=translate&text=%s", URLEncoder.encode(text, "UTF-8")); + break; + case -2: + url = String.format("https://translate.google.cn/?view=home&op=translate&text=%s", URLEncoder.encode(text, "UTF-8")); + break; + case -3: + url = String.format("https://fanyi.baidu.com/?aldtype=38319&tpltype=sigma#auto/zh/%s", TransUtils.encodeURIComponent(text)); + break; + case -4: + url = String.format("https://www.deepl.com/translator#auto/auto/%s", TransUtils.encodeURIComponent(text)); + break; + } + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + containerLayout = new FrameLayout(context) { + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + try { + if ((webView.getVisibility() != VISIBLE) && webView.getParent() != null) { + removeView(webView); + webView.stopLoading(); + webView.loadUrl("about:blank"); + webView.destroy(); + } + } catch (Exception e) { + FileLog.e(e); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int h = (int) (AndroidUtilities.displaySize.y / 1.5); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h + AndroidUtilities.dp(48) + 1, MeasureSpec.EXACTLY)); + } + }; + containerLayout.setOnTouchListener((v, event) -> true); + setCustomView(containerLayout); + + webView = new WebView(context); + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setDomStorageEnabled(true); + if (Build.VERSION.SDK_INT >= 17) { + webView.getSettings().setMediaPlaybackRequiresUserGesture(false); + } + + if (Build.VERSION.SDK_INT >= 21) { + webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); + CookieManager cookieManager = CookieManager.getInstance(); + cookieManager.setAcceptThirdPartyCookies(webView, true); + } + + webView.setWebViewClient(new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + progressBar.setVisibility(View.INVISIBLE); + + } + }); + + containerLayout.addView(webView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 48)); + + progressBar = new RadialProgressView(context); + progressBar.setVisibility(View.INVISIBLE); + containerLayout.addView(progressBar, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, (48) / 2)); + + View lineView = new View(context); + lineView.setBackgroundColor(Theme.getColor(Theme.key_dialogGrayLine)); + containerLayout.addView(lineView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1, Gravity.LEFT | Gravity.BOTTOM)); + ((FrameLayout.LayoutParams) lineView.getLayoutParams()).bottomMargin = AndroidUtilities.dp(48); + + FrameLayout frameLayout = new FrameLayout(context); + frameLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + containerLayout.addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); + linearLayout.setWeightSum(1); + frameLayout.addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); + + TextView textView = new TextView(context); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue4)); + textView.setGravity(Gravity.CENTER); + textView.setSingleLine(true); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 0)); + textView.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); + textView.setText(LocaleController.getString("Close", R.string.Close).toUpperCase()); + textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + frameLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); + textView.setOnClickListener(v -> dismiss()); + + TextView openInButton = new TextView(context); + openInButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + openInButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue4)); + openInButton.setGravity(Gravity.CENTER); + openInButton.setSingleLine(true); + openInButton.setEllipsize(TextUtils.TruncateAt.END); + openInButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 0)); + openInButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); + openInButton.setText(LocaleController.getString("OpenInBrowser", R.string.OpenInBrowser).toUpperCase()); + openInButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + linearLayout.addView(openInButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); + openInButton.setOnClickListener(v -> { + Browser.openUrl(parentActivity, url); + dismiss(); + }); + + setDelegate(new BottomSheet.BottomSheetDelegate() { + @Override + public void onOpenAnimationEnd() { + progressBar.setVisibility(View.VISIBLE); + webView.setVisibility(View.VISIBLE); + try { + webView.loadUrl(url); + } catch (Exception e) { + FileLog.e(e); + } + + } + + }); + + instance = this; + } + + public static void show(Context context, final String text) { + if (instance != null) { + instance.destroy(); + } + new TranslateBottomSheet(context, text).show(); + } + + public static TranslateBottomSheet getInstance() { + return instance; + } + + public void destroy() { + if (webView != null && webView.getVisibility() == View.VISIBLE) { + containerLayout.removeView(webView); + webView.stopLoading(); + webView.loadUrl("about:blank"); + webView.destroy(); + } + instance = null; + dismissInternal(); + } + +} diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TranslateDb.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TranslateDb.kt new file mode 100644 index 000000000..f500e0dd4 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/TranslateDb.kt @@ -0,0 +1,72 @@ +package tw.nekomimi.nekogram.transtale + +import org.dizitart.no2.objects.ObjectRepository +import org.dizitart.no2.objects.filters.ObjectFilters +import org.telegram.messenger.LocaleController +import tw.nekomimi.nekogram.NekoConfig +import tw.nekomimi.nekogram.database.mkDatabase +import tw.nekomimi.nekogram.utils.UIUtil +import java.util.* +import kotlin.collections.HashMap + +class TranslateDb(val code: String) { + + var conn: ObjectRepository = db.getRepository(code, TransItem::class.java) + + companion object { + + val db = mkDatabase("translate_caches") + + val repo = HashMap() + val chat = db.getRepository(ChatLanguage::class.java) + + @JvmStatic fun getChatLanguage(chatId: Int, default: Locale): Locale { + + return chat.find(ObjectFilters.eq("chatId", chatId)).firstOrDefault()?.language?.code2Locale ?: default + + } + + @JvmStatic fun saveChatLanguage(chatId: Int, locale: Locale) = UIUtil.runOnIoDispatcher { + + chat.update(ChatLanguage(chatId, locale.locale2code), true) + + } + + @JvmStatic fun currentTarget() = NekoConfig.translateToLang?.transDbByCode ?: LocaleController.getInstance().currentLocale.transDb + + @JvmStatic fun forLocale(locale: Locale) = locale.transDb + + @JvmStatic fun currentInputTarget() = NekoConfig.translateInputLang.transDbByCode + + @JvmStatic fun clearAll() { + + db.listRepositories().map { it.transDbByCode }.forEach { it.clear() } + + repo.clear() + + } + + } + + fun clear() = synchronized(this) { + + conn.drop() + conn = db.getRepository(code, TransItem::class.java) + + } + + fun contains(text: String) = synchronized(this) { conn.find(ObjectFilters.eq("text", text)).count() > 0 } + + fun save(text: String, trans: String) = synchronized(this) { + + conn.update(TransItem(text, trans), true) + + } + + fun query(text: String) = synchronized(this) { + + conn.find(ObjectFilters.eq("text", text)).firstOrDefault()?.trans + + } + +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/Translator.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/Translator.kt new file mode 100644 index 000000000..0f85842b7 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/Translator.kt @@ -0,0 +1,207 @@ +package tw.nekomimi.nekogram.transtale + +import android.view.View +import cn.hutool.core.util.ArrayUtil +import cn.hutool.core.util.StrUtil +import org.apache.commons.lang3.LocaleUtils +import org.telegram.messenger.LocaleController +import org.telegram.messenger.R +import tw.nekomimi.nekogram.NekoConfig +import tw.nekomimi.nekogram.transtale.source.GoogleWebTranslator +import tw.nekomimi.nekogram.transtale.source.LingoTranslator +import tw.nekomimi.nekogram.transtale.source.YandexTranslator +import tw.nekomimi.nekogram.utils.PopupBuilder +import tw.nekomimi.nekogram.utils.UIUtil +import tw.nekomimi.nekogram.utils.receive +import tw.nekomimi.nekogram.utils.receiveLazy +import java.util.* + +val String.code2Locale: Locale by receiveLazy { + + val args = replace('-', '_').split('_') + + if (args.size == 1) Locale(args[0]) else Locale(args[0], args[1]) + +} + +val Locale.locale2code by receiveLazy { + + if (StrUtil.isBlank(getCountry())) { + language + } else { + "$language-$country" + } + +} + +val LocaleController.LocaleInfo.locale by receiveLazy { pluralLangCode.code2Locale } + +val Locale.transDb by receive { + + TranslateDb.repo[this] ?: TranslateDb(locale2code).also { + + TranslateDb.repo[this] = it + + } + +} + +val String.transDbByCode by receive { code2Locale.transDb } + +interface Translator { + + fun doTranslate(from: String, to: String, query: String): String + + companion object { + + @Throws(Exception::class) + @JvmStatic + fun translate(query: String) = translate(NekoConfig.translateToLang?.code2Locale ?: LocaleController.getInstance().currentLocale, query) + + @Throws(Exception::class) + @JvmStatic + fun translate(to: Locale, query: String): String { + + var toLang = to.language + + val country = to.country + + if (country.toLowerCase() == "duang") { + + country == "CN" + + } + + if (NekoConfig.translationProvider < 3) { + + if (to.language == "zh" && (country.toUpperCase() == "CN" || country.toUpperCase() == "TW")) { + toLang = to.language + "-" + country.toUpperCase() + } else if (to.language == "pt" && country in arrayOf("PT", "BR")) { + toLang = to.language + "-" + country.toUpperCase() + } + + } + + val translator = when (NekoConfig.translationProvider) { + in 1..2 -> GoogleWebTranslator + 3 -> LingoTranslator + 4 -> YandexTranslator + else -> throw IllegalArgumentException() + } + + // FileLog.d("[Trans] use provider ${translator.javaClass.simpleName}, toLang: $toLang, query: $query") + + return translator.doTranslate("auto", toLang, query).also { + + to.transDb.save(query, it) + + } + + } + + @JvmStatic @JvmOverloads fun showTargetLangSelect(anchor: View, input: Boolean = false, full: Boolean = false, callback: (Locale) -> Unit) { + + val builder = PopupBuilder(anchor) + + var locales = (if (full) LocaleUtils.availableLocaleList() + .filter { it.variant.isBlank() } else LocaleController.getInstance() + .languages + .map { it.pluralLangCode } + .toSet() + .filter { !it.toLowerCase().contains("duang") } + .map { it.code2Locale }) + .toTypedArray() + + val currLocale = LocaleController.getInstance().currentLocale + + for (i in locales.indices) { + + val defLang = if (!input) currLocale else Locale.ENGLISH + + if (locales[i] == defLang) { + + locales = ArrayUtil.remove(locales, i) + locales = ArrayUtil.insert(locales, 0, defLang) + + break + + } + + } + + val localeNames = arrayOfNulls(if (full) locales.size else locales.size + 1) + + for (i in locales.indices) { + + localeNames[i] = if (!full && i == 0) { + + LocaleController.getString("Default", R.string.Default) + " ( " + locales[i].getDisplayName(currLocale) + " )" + + } else { + + locales[i].getDisplayName(currLocale) + + } + + } + + if (!full) { + + localeNames[localeNames.size - 1] = LocaleController.getString("More", R.string.More) + + } + + builder.setItems(localeNames.filterIsInstance().toTypedArray()) { index: Int, _ -> + + if (index == locales.size) { + + showTargetLangSelect(anchor, input, true, callback) + + } else { + + callback(locales[index]) + + } + + } + + builder.show() + + } + + @JvmStatic + @JvmOverloads + fun translate(to: Locale = NekoConfig.translateToLang?.code2Locale ?: LocaleController.getInstance().currentLocale, query: String, translateCallBack: TranslateCallBack) { + + UIUtil.runOnIoDispatcher(Runnable { + + runCatching { + + val result = translate(to, query) + + UIUtil.runOnUIThread(Runnable { + + translateCallBack.onSuccess(result) + + }) + + }.onFailure { + + translateCallBack.onFailed(it is UnsupportedOperationException, it.message ?: it.javaClass.simpleName) + + } + + }) + + } + + interface TranslateCallBack { + + fun onSuccess(translation: String) + fun onFailed(unsupported: Boolean, message: String) + + } + + } + +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/GoogleCloudTranslator.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/GoogleCloudTranslator.kt new file mode 100644 index 000000000..b341661a5 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/GoogleCloudTranslator.kt @@ -0,0 +1,73 @@ +package tw.nekomimi.nekogram.transtale.source + +import cn.hutool.core.util.StrUtil +import okhttp3.FormBody +import okhttp3.Request +import org.json.JSONObject +import org.telegram.messenger.LocaleController +import org.telegram.messenger.R +import tw.nekomimi.nekogram.NekoConfig +import tw.nekomimi.nekogram.transtale.Translator +import tw.nekomimi.nekogram.utils.HttpUtil + +object GoogleCloudTranslator : Translator { + + override fun doTranslate(from: String, to: String, query: String): String { + + if (to !in targetLanguages) { + + throw UnsupportedOperationException(LocaleController.getString("TranslateApiUnsupported", R.string.TranslateApiUnsupported)) + + } + + if (StrUtil.isBlank(NekoConfig.googleCloudTranslateKey)) error("Missing Cloud Translate Key") + + val request = Request.Builder() + .url("https://translation.googleapis.com/language/translate/v2") + .post(FormBody.Builder() + .add("q", query) + .add("target", to) + .add("format", "text") + .add("key", NekoConfig.googleCloudTranslateKey) + .apply { + if (from != "auto") add("source", from) + } + .build()).build() + + val response = runCatching { + HttpUtil.okHttpClient.newCall(request).execute() + }.recoverCatching { + HttpUtil.okHttpClientWithCurrProxy.newCall(request).execute() + }.getOrThrow() + + if (response.code != 200) { + + error("HTTP ${response.code} : ${response.body?.string()}") + + } + + var respObj = JSONObject(response.body!!.string()) + + if (respObj.isNull("data")) error(respObj.toString(4)) + + respObj = respObj.getJSONObject("data") + + val respArr = respObj.getJSONArray("translations") + + if (respArr.length() == 0) error("Empty translation result") + + return respArr.getJSONObject(0).getString("translatedText") + + } + + private val targetLanguages = listOf( + "sq", "ar", "am", "az", "ga", "et", "eu", "be", "bg", "is", "pl", "bs", "fa", + "af", "da", "de", "ru", "fr", "tl", "fi", "fy", "km", "ka", "gu", "kk", "ht", + "ko", "ha", "nl", "ky", "gl", "ca", "cs", "kn", "co", "hr", "ku", "la", "lv", + "lo", "lt", "lb", "ro", "mg", "mt", "mr", "ml", "ms", "mk", "mi", "mn", "bn", + "my", "hmn", "xh", "zu", "ne", "no", "pa", "pt", "ps", "ny", "ja", "sv", "sm", + "sr", "st", "si", "eo", "sk", "sl", "sw", "gd", "ceb", "so", "tg", "te", "ta", + "th", "tr", "cy", "ur", "uk", "uz", "es", "iw", "el", "haw", "sd", "hu", "sn", + "hy", "ig", "it", "yi", "hi", "su", "id", "jw", "en", "yo", "vi", "zh-TW", "zh-CN", "zh") + +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/GoogleWebTranslator.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/GoogleWebTranslator.kt new file mode 100644 index 000000000..889802e17 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/GoogleWebTranslator.kt @@ -0,0 +1,90 @@ +package tw.nekomimi.nekogram.transtale.source + +import android.text.TextUtils +import cn.hutool.core.util.StrUtil +import okhttp3.Request +import org.json.JSONArray +import org.telegram.messenger.LocaleController +import org.telegram.messenger.R +import tw.nekomimi.nekogram.NekoConfig +import tw.nekomimi.nekogram.NekoXPushService +import tw.nekomimi.nekogram.transtale.TransUtils +import tw.nekomimi.nekogram.transtale.Translator +import tw.nekomimi.nekogram.utils.HttpUtil +import tw.nekomimi.nekogram.utils.applyUserAgent +import java.util.* +import java.util.regex.Pattern + +object GoogleWebTranslator : Translator { + + lateinit var tkk: LongArray + + override fun doTranslate(from: String, to: String, query: String): String { + + if (NekoConfig.translationProvider != 2 && StrUtil.isNotBlank(NekoConfig.googleCloudTranslateKey)) return GoogleCloudTranslator.doTranslate(from, to, query) + + if (to !in targetLanguages) { + + throw UnsupportedOperationException(LocaleController.getString("TranslateApiUnsupported", R.string.TranslateApiUnsupported)) + + } + + if (!GoogleWebTranslator::tkk.isInitialized) { + + val response = HttpUtil.get("https://translate.google." + if (NekoConfig.translationProvider == 2) "cn" else "com") + + if (TextUtils.isEmpty(response)) { + + error("Tkk init failed") + + } + + val matcher = Pattern.compile("tkk\\s*[:=]\\s*['\"]([0-9]+)\\.([0-9]+)['\"]", Pattern.CASE_INSENSITIVE or Pattern.UNICODE_CASE).matcher(response) + + tkk = if (matcher.find() && matcher.group(1) != null && matcher.group(2) != null) { + longArrayOf(matcher.group(1).toLong(), matcher.group(2).toLong()) + } else error("Tkk match failed") + + } + + val tk = TransUtils.signWeb(query, tkk[0], tkk[1]) + + val url = "https://translate.google." + (if (NekoConfig.translationProvider == 2) "cn" else "com") + "/translate_a/single?client=webapp&dt=t&sl=auto" + + "&tl=" + to + + "&tk=" + tk + + "&q=" + TransUtils.encodeURIComponent(query) // 不能用URLEncoder + + val response = runCatching { + (if (NekoConfig.translationProvider == 2) HttpUtil.okHttpClientNoDoh else HttpUtil.okHttpClient).newCall(Request.Builder().url(url).applyUserAgent().build()).execute() + }.recoverCatching { + HttpUtil.okHttpClientWithCurrProxy.newCall(Request.Builder().url(url).applyUserAgent().build()).execute() + }.getOrThrow() + + if (response.code != 200) { + + error("HTTP ${response.code} : ${response.body?.string()}") + + } + + val result = StringBuilder() + + val array = JSONArray(response.body!!.string()).getJSONArray(0) + for (index in 0 until array.length()) { + result.append(array.getJSONArray(index).getString(0)) + } + + return result.toString() + } + + private val targetLanguages = listOf( + "sq", "ar", "am", "az", "ga", "et", "eu", "be", "bg", "is", "pl", "bs", "fa", + "af", "da", "de", "ru", "fr", "tl", "fi", "fy", "km", "ka", "gu", "kk", "ht", + "ko", "ha", "nl", "ky", "gl", "ca", "cs", "kn", "co", "hr", "ku", "la", "lv", + "lo", "lt", "lb", "ro", "mg", "mt", "mr", "ml", "ms", "mk", "mi", "mn", "bn", + "my", "hmn", "xh", "zu", "ne", "no", "pa", "pt", "ps", "ny", "ja", "sv", "sm", + "sr", "st", "si", "eo", "sk", "sl", "sw", "gd", "ceb", "so", "tg", "te", "ta", + "th", "tr", "cy", "ur", "uk", "uz", "es", "iw", "el", "haw", "sd", "hu", "sn", + "hy", "ig", "it", "yi", "hi", "su", "id", "jw", "en", "yo", "vi", "zh-TW", "zh-CN", "zh") + + +} diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/LingoTranslator.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/LingoTranslator.kt new file mode 100644 index 000000000..a52e9a2f6 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/LingoTranslator.kt @@ -0,0 +1,52 @@ +package tw.nekomimi.nekogram.transtale.source + +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import org.telegram.messenger.LocaleController +import org.telegram.messenger.R +import tw.nekomimi.nekogram.transtale.Translator +import tw.nekomimi.nekogram.utils.HttpUtil +import tw.nekomimi.nekogram.utils.applyUserAgent + +object LingoTranslator : Translator { + + override fun doTranslate(from: String, to: String, query: String): String { + + if (to !in listOf("zh", "en", "es", "fr", "ja", "ru")) { + + error(LocaleController.getString("TranslateApiUnsupported", R.string.TranslateApiUnsupported)) + + } + + val request = Request.Builder() + .url("https://api.interpreter.caiyunai.com/v1/translator") + .header("Content-Type", "application/json; charset=UTF-8") + .header("X-Authorization", "token 9sdftiq37bnv410eon2l") // 白嫖 + .applyUserAgent() + .post(JSONObject().apply { + + put("source", query) + put("trans_type", "${from}2$to") + put("request_id", System.currentTimeMillis().toString()) + put("detect", true) + + }.toString().toRequestBody()).build() + + val response = runCatching { + HttpUtil.okHttpClient.newCall(request).execute() + }.recoverCatching { + HttpUtil.okHttpClientWithCurrProxy.newCall(request).execute() + }.getOrThrow() + + if (response.code != 200) { + + error("HTTP ${response.code} : ${response.body?.string()}") + + } + + return JSONObject(response.body!!.string()).getString("target") + + } + +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/YandexTranslator.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/YandexTranslator.kt new file mode 100644 index 000000000..bc5fd27c7 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/transtale/source/YandexTranslator.kt @@ -0,0 +1,48 @@ +package tw.nekomimi.nekogram.transtale.source + +import cn.hutool.core.lang.UUID +import okhttp3.FormBody +import okhttp3.Request +import org.json.JSONObject +import tw.nekomimi.nekogram.NekoConfig +import tw.nekomimi.nekogram.transtale.Translator +import tw.nekomimi.nekogram.utils.HttpUtil +import tw.nekomimi.nekogram.utils.applyUserAgent + +object YandexTranslator : Translator { + + val uuid = UUID.fastUUID().toString(true) + + override fun doTranslate(from: String, to: String, query: String): String { + + val uuid2 = UUID.fastUUID().toString(true) + + val request = Request.Builder() + .url("https://translate.yandex.net/api/v1/tr.json/translate?srv=android&uuid=$uuid&id=$uuid2-9-0") + .applyUserAgent() + .post(FormBody.Builder() + .add("text", query) + .add("lang", if (from == "auto") to else "$from-$to") + .build()).build() + + val response = runCatching { + HttpUtil.okHttpClient.newCall(request).execute() + }.recoverCatching { + HttpUtil.okHttpClientWithCurrProxy.newCall(request).execute() + }.getOrThrow() + + if (response.code != 200) { + + error("HTTP ${response.code} : ${response.body?.string()}") + + } + + val respObj = JSONObject(response.body!!.string()) + + if (respObj.optInt("code",-1) != 200) error(respObj.toString(4)) + + return respObj.getJSONArray("text").getString(0) + + } + +} \ No newline at end of file