Translates

This commit is contained in:
世界 2020-06-25 15:28:44 +00:00
parent dd08362cc6
commit 1cec9e7b36
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
25 changed files with 3178 additions and 742 deletions

View File

@ -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<TLRPC.TL_pollAnswer> 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() {

View File

@ -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;

View File

@ -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<BlockEmbedCell> 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<TLRPC.PageBlock> localBlocks = new ArrayList<>();
@ -5120,14 +5191,16 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
private HashMap<String, TLRPC.TL_textAnchor> anchorsParent = new HashMap<>();
private HashMap<TLRPC.TL_pageBlockAudio, MessageObject> audioBlocks = new HashMap<>();
private ArrayList<MessageObject> audioMessages = new ArrayList<>();
private HashMap<Object, TLRPC.PageBlock> textToBlocks = new HashMap<>();
private ArrayList<Object> textBlocks = new ArrayList<>();
public HashMap<Object, TLRPC.PageBlock> textToBlocks = new HashMap<>();
public ArrayList<Object> textBlocks = new ArrayList<>();
private HashMap<String, Integer> 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<TextSelectionHelper.TextLayoutBlock> 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);

View File

@ -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

View File

@ -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;

View File

@ -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<Cell extends TextSelectionHelper.Selec
final ActionMode.Callback callback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
menu.add(Menu.NONE, android.R.id.copy, 0, android.R.string.copy);
menu.add(Menu.NONE, android.R.id.selectAll, 1, android.R.string.selectAll);
menu.add(Menu.NONE, R.id.menu_translate, 2, R.string.Translate);
menu.add(Menu.NONE, 0, 0, android.R.string.copy);
menu.add(Menu.NONE, 1, 1, android.R.string.selectAll);
menu.add(Menu.NONE, 2, 2, R.string.Translate);
return true;
}
@ -1231,6 +1239,7 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
} else {
menu.getItem(1).setVisible(true);
}
menu.getItem(2).setVisible(selectedView instanceof View);
}
return true;
}
@ -1241,10 +1250,10 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
return true;
}
switch (item.getItemId()) {
case android.R.id.copy:
case 0:
copyText();
return true;
case android.R.id.selectAll:
case 1: {
CharSequence text = getText(selectedView, false);
if (text == null) {
return true;
@ -1255,19 +1264,38 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
invalidate();
showActions();
return true;
case R.id.menu_translate:
if (!isSelectionMode()) {
}
case 2:
CharSequence textS = getTextForCopy();
if (textS == null) {
return true;
}
CharSequence str = getTextForCopy();
if (str == null) {
return true;
}
MessageHelper.showTranslateDialog(textSelectionOverlay.getContext(), str.toString());
hideActions();
clear(true);
if (TextSelectionHelper.this.callback != null) {
TextSelectionHelper.this.callback.onTextCopied();
String urlFinal = textS.toString();
Activity activity = ProxyUtil.getOwnerActivity((((View) selectedView).getContext()));
if (NekoConfig.translationProvider < 0) {
TranslateBottomSheet.show(activity, urlFinal);
} else {
TranslateDb db = TranslateDb.currentTarget();
if (db.contains(urlFinal)) {
AlertUtil.showCopyAlert(activity, db.query(urlFinal));
} else {
AlertDialog pro = AlertUtil.showProgress(activity);
pro.show();
Translator.translate(urlFinal, new Translator.Companion.TranslateCallBack() {
@Override public void onSuccess(@NotNull String translation) {
pro.dismiss();
AlertUtil.showCopyAlert(activity, translation);
}
@Override public void onFailed(boolean unsupported, @NotNull String message) {
pro.dismiss();
AlertUtil.showTransFailedDialog(activity, unsupported, message, () -> {
pro.show();
Translator.translate(urlFinal, this);
});
}
});
}
}
default:
clear();

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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));

View File

@ -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;
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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<MessageObject> imagesArrTemp = new ArrayList<>();
private SparseArray<MessageObject>[] imagesByIdsTemp = new SparseArray[] {new SparseArray<>(), new SparseArray<>()};
private SparseArray<MessageObject>[] imagesByIdsTemp = new SparseArray[]{new SparseArray<>(), new SparseArray<>()};
private ArrayList<MessageObject> imagesArr = new ArrayList<>();
private SparseArray<MessageObject>[] imagesByIds = new SparseArray[] {new SparseArray<>(), new SparseArray<>()};
private SparseArray<MessageObject>[] imagesByIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()};
private ArrayList<ImageLocation> imagesArrLocations = new ArrayList<>();
private ArrayList<SecureDocument> secureDocuments = new ArrayList<>();
private ArrayList<TLRPC.Photo> 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<Object, Object> hashMap = placeProvider.getSelectedPhotos();
boolean hasTtl = false;
for (HashMap.Entry<Object, Object> 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<TLRPC.MessageEntity> 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 {

View File

@ -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<Any>.filterBaseTexts(): HashSet<Any> {
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<Deferred<Unit>>()
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()
}
})
}
}

View File

@ -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<MessageObject>, 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
}
}
}
}

View File

@ -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"));
}
}

View File

@ -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");
}
}

View File

@ -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<Integer> 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();
}
}

View File

@ -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();
}
}

View File

@ -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<TransItem> = db.getRepository(code, TransItem::class.java)
companion object {
val db = mkDatabase("translate_caches")
val repo = HashMap<Locale, TranslateDb>()
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<Unit>(this) {
conn.update(TransItem(text, trans), true)
}
fun query(text: String) = synchronized(this) {
conn.find(ObjectFilters.eq("text", text)).firstOrDefault()?.trans
}
}

View File

@ -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<String, Locale> {
val args = replace('-', '_').split('_')
if (args.size == 1) Locale(args[0]) else Locale(args[0], args[1])
}
val Locale.locale2code by receiveLazy<Locale, String> {
if (StrUtil.isBlank(getCountry())) {
language
} else {
"$language-$country"
}
}
val LocaleController.LocaleInfo.locale by receiveLazy<LocaleController.LocaleInfo, Locale> { pluralLangCode.code2Locale }
val Locale.transDb by receive<Locale, TranslateDb> {
TranslateDb.repo[this] ?: TranslateDb(locale2code).also {
TranslateDb.repo[this] = it
}
}
val String.transDbByCode by receive<String, TranslateDb> { 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<String>(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<CharSequence>().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)
}
}
}

View File

@ -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")
}

View File

@ -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")
}

View File

@ -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")
}
}

View File

@ -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)
}
}