This commit is contained in:
世界 2020-04-09 15:00:38 +08:00
parent 93d325de46
commit ea6b589b6d
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
31 changed files with 631 additions and 626 deletions

View File

@ -147,6 +147,8 @@ public class FileLoadOperation {
private ArrayList<RequestInfo> requestInfos;
private ArrayList<RequestInfo> delayedRequestInfos;
private String fileName;
private File cacheFileTemp;
private File cacheFileGzipTemp;
private File cacheFileFinal;
@ -266,7 +268,8 @@ public class FileLoadOperation {
ext = ImageLoader.getHttpUrlExtension(webDocument.url, defaultExt);
}
public FileLoadOperation(TLRPC.Document documentLocation, Object parent) {
public FileLoadOperation(TLRPC.Document documentLocation, Object parent,String fileName) {
this.fileName = fileName;
try {
parentObject = parent;
if (documentLocation instanceof TLRPC.TL_documentEncrypted) {
@ -718,6 +721,8 @@ public class FileLoadOperation {
if (parentObject instanceof TLRPC.TL_theme) {
TLRPC.TL_theme theme = (TLRPC.TL_theme) parentObject;
cacheFileFinal = new File(ApplicationLoader.getFilesDirFixed(), "remote" + theme.id + ".attheme");
} else if (fileName != null) {
cacheFileFinal = new File(storePath, fileName);
} else {
cacheFileFinal = new File(storePath, fileNameFinal);
}

View File

@ -612,7 +612,7 @@ public class FileLoader extends BaseController {
operation = new FileLoadOperation(imageLocation, parentObject, locationExt, locationSize);
type = MEDIA_DIR_IMAGE;
} else if (document != null) {
operation = new FileLoadOperation(document, parentObject);
operation = new FileLoadOperation(document, parentObject,fileName);
if (MessageObject.isVoiceDocument(document)) {
type = MEDIA_DIR_AUDIO;
} else if (MessageObject.isVideoDocument(document)) {

View File

@ -246,9 +246,6 @@ public class FileUploadOperation {
started = true;
if (stream == null) {
File cacheFile = new File(uploadingFilePath);
if (AndroidUtilities.isInternalUri(Uri.fromFile(cacheFile))) {
throw new Exception("trying to upload internal file");
}
stream = new RandomAccessFile(cacheFile, "r");
if (estimatedSize != 0) {
totalFileSize = estimatedSize;

View File

@ -472,6 +472,16 @@ public class ActionBarMenuItem extends FrameLayout {
this.anchor = anchor;
}
public boolean isShowOnTop() {
return showOnTop;
}
public void setShowOnTop(boolean showOnTop) {
this.showOnTop = showOnTop;
}
private boolean showOnTop;
public void toggleSubMenu() {
if (popupLayout == null || parentMenu != null && parentMenu.isActionMode && parentMenu.parentActionBar != null && !parentMenu.parentActionBar.isActionModeShowed()) {
return;
@ -958,7 +968,9 @@ public class ActionBarMenuItem extends FrameLayout {
int[] location = new int[2];
anchor.getLocationOnScreen(location);
int y = location[1];
if (height - y < popupLayout.getMeasuredHeight() + offsetY) {
if (showOnTop) {
offsetY -= popupLayout.getMeasuredHeight();
} else if (height - y < popupLayout.getMeasuredHeight() + offsetY) {
if (height - (height - y) >= popupLayout.getMeasuredHeight()) {
offsetY -= popupLayout.getMeasuredHeight();
} else if (popupLayout.getMeasuredHeight() > height) {

View File

@ -183,7 +183,6 @@ import org.telegram.ui.Components.VideoPlayer;
import org.telegram.ui.Components.WebPlayerView;
import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
@ -195,8 +194,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import tw.nekomimi.nekogram.NekoConfig;
import tw.nekomimi.nekogram.translator.TranslateDb;
import tw.nekomimi.nekogram.translator.Translator;
import tw.nekomimi.nekogram.transtale.Translator;
import tw.nekomimi.nekogram.transtale.TranslateDb;
import tw.nekomimi.nekogram.utils.AlertUtil;
import tw.nekomimi.nekogram.utils.UIUtil;
@ -4094,61 +4093,68 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
ArrayList<Object> array = new ArrayList<>(adapter[0].textBlocks);
AtomicInteger errorCount = new AtomicInteger();
AtomicInteger taskCount = new AtomicInteger(array.size());
for (int b = 0, N = array.size(); b < N; b++) {
Object object = array.get(b);
TLRPC.PageBlock block = copy.get(object);
String textToSearchIn = null;
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();
try {
for (int b = 0, N = array.size(); b < N; b++) {
Object object = array.get(b);
TLRPC.PageBlock block = copy.get(object);
String textToSearchIn = null;
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();
}
} else if (object instanceof String) {
textToSearchIn = ((String) object);
}
} else if (object instanceof String) {
textToSearchIn = ((String) object);
}
if (textToSearchIn != null) {
if (TranslateDb.contains(textToSearchIn)) {
taskCount.decrementAndGet();
continue;
}
String finalTextToSearchIn = textToSearchIn;
transPool.execute(() -> {
if (textToSearchIn != null) {
if (TranslateDb.contains(textToSearchIn)) {
taskCount.decrementAndGet();
continue;
}
String finalTextToSearchIn = textToSearchIn;
if (cancel.get()) return;
transPool.execute(() -> {
String localeText;
try {
localeText = Translator.translateSync(finalTextToSearchIn);
if (cancel.get()) return;
} catch (IOException e) {
if (cancel.get()) return;
boolean finaL = taskCount.decrementAndGet() == 0;
if (errorCount.incrementAndGet() > 3 || finaL) {
UIUtil.runOnUIThread(dialog::dismiss);
adapter[0].trans = false;
transMenu.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate);
AlertUtil.showSimpleAlert(parentActivity, e.getMessage());
cancel.set(true);
transPool.shutdown();
String localeText;
try {
localeText = Translator.translate(finalTextToSearchIn);
if (cancel.get()) return;
} catch (Exception e) {
if (cancel.get()) return;
boolean finaL = taskCount.decrementAndGet() == 0;
if (errorCount.incrementAndGet() > 3 || finaL) {
UIUtil.runOnUIThread(dialog::dismiss);
adapter[0].trans = false;
transMenu.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate);
AlertUtil.showSimpleAlert(parentActivity, e.getMessage());
cancel.set(true);
transPool.shutdown();
AlertUtil.showTransFailedDialog(parentActivity, e instanceof UnsupportedOperationException, e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage(), this::doTransLATE);
}
return;
}
return;
}
TranslateDb.save(finalTextToSearchIn, localeText);
UIUtil.runOnUIThread(this::updatePaintSize);
TranslateDb.save(finalTextToSearchIn, localeText);
UIUtil.runOnUIThread(this::updatePaintSize);
boolean finaL = taskCount.decrementAndGet() == 0;
boolean finaL = taskCount.decrementAndGet() < 1;
if (finaL) {
if (finaL) {
UIUtil.runOnUIThread(dialog::dismiss);
transPool.shutdown();
UIUtil.runOnUIThread(dialog::dismiss);
transPool.shutdown();
}
}
});
});
}
}
} catch (Exception ignored) {
dialog.dismiss();
UIUtil.runOnUIThread(this::updatePaintSize);
}
if (taskCount.get() == 0) {
dialog.dismiss();

View File

@ -94,6 +94,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import org.jetbrains.annotations.NotNull;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
@ -214,6 +215,7 @@ import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -221,9 +223,9 @@ import tw.nekomimi.nekogram.MessageDetailsActivity;
import tw.nekomimi.nekogram.MessageHelper;
import tw.nekomimi.nekogram.NekoConfig;
import tw.nekomimi.nekogram.NekoXConfig;
import tw.nekomimi.nekogram.translator.TranslateBottomSheet;
import tw.nekomimi.nekogram.translator.TranslateDb;
import tw.nekomimi.nekogram.translator.Translator;
import tw.nekomimi.nekogram.transtale.Translator;
import tw.nekomimi.nekogram.transtale.TranslateBottomSheet;
import tw.nekomimi.nekogram.transtale.TranslateDb;
import tw.nekomimi.nekogram.utils.AlertUtil;
import tw.nekomimi.nekogram.utils.StrUtil;
@ -15326,9 +15328,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
chatAdapter.updateRowWithMessageObject(messageObject, true);
}
} else {
Translator.translate(original, new Translator.TranslateCallBack() {
Translator.translate(original, new Translator.Companion.TranslateCallBack() {
@Override
public void onSuccess(String translation) {
public void onSuccess(@NotNull String translation) {
TranslateDb.save(original,translation);
if (finalMessageCell != null) {
MessageObject messageObject = finalMessageCell.getMessageObject();
@ -15344,21 +15347,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
@Override
public void onError() {
try {
Toast.makeText(getParentActivity(), LocaleController.getString("TranslateFailed", R.string.TranslateFailed), Toast.LENGTH_SHORT).show();
} catch (Exception e) {
FileLog.e(e);
}
}
@Override
public void onUnsupported() {
try {
Toast.makeText(getParentActivity(), LocaleController.getString("TranslateApiUnsupported", R.string.TranslateApiUnsupported), Toast.LENGTH_SHORT).show();
} catch (Exception e) {
FileLog.e(e);
}
public void onFailed(boolean unsupported, @NotNull String message) {
AlertUtil.showTransFailedDialog(getParentActivity(),unsupported,message,() -> {
Translator.translate(original,this);
});
}
});
}

View File

@ -45,7 +45,6 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.json.JSONArray;
@ -60,25 +59,13 @@ import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.TLRPC;
import tw.nekomimi.nekogram.utils.HttpUtil;
import tw.nekomimi.nekogram.utils.ThreadUtil;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
@ -87,7 +74,6 @@ import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
public class WebPlayerView extends ViewGroup implements VideoPlayer.VideoPlayerDelegate, AudioManager.OnAudioFocusChangeListener {
@ -456,7 +442,7 @@ public class WebPlayerView extends ViewGroup implements VideoPlayer.VideoPlayerD
protected String downloadUrlContent(AsyncTask parentTask, String url, HashMap<String, String> headers, boolean tryGzip) {
OkHttpClient client = HttpUtil.getOkhttpClientWithCurrProxy().newBuilder()
OkHttpClient client = HttpUtil.getOkHttpClientWithCurrProxy().newBuilder()
.followRedirects(true)
.followSslRedirects(true)
.build();

View File

@ -44,7 +44,8 @@ import java.util.TimerTask;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import tw.nekomimi.nekogram.translator.TranslateDb;
import tw.nekomimi.nekogram.transtale.TranslateDb;
import tw.nekomimi.nekogram.utils.UIUtil;
public class LanguageSelectActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
@ -154,8 +155,8 @@ public class LanguageSelectActivity extends BaseFragment implements Notification
if (localeInfo != null) {
LocaleController.getInstance().applyLanguage(localeInfo, true, false, false, true, currentAccount);
parentLayout.rebuildAllFragmentViews(false, false);
TranslateDb.clear();
}
UIUtil.runOnIoDispatcher(TranslateDb::clear);
finishFragment();
});

View File

@ -13,6 +13,8 @@ import org.telegram.messenger.NotificationsService;
import org.telegram.messenger.SharedConfig;
import tw.nekomimi.nekogram.database.NitritesKt;
import tw.nekomimi.nekogram.transtale.TranslateDb;
import tw.nekomimi.nekogram.utils.UIUtil;
@SuppressLint("ApplySharedPref")
public class NekoConfig {
@ -369,6 +371,7 @@ public class NekoConfig {
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("translationProvider", translationProvider);
editor.apply();
UIUtil.runOnIoDispatcher(TranslateDb::clear);
}
public static void toggleDisablePhotoSideAction() {

View File

@ -54,6 +54,7 @@ import org.telegram.ui.Components.SeekBarView;
import java.util.ArrayList;
import kotlin.Unit;
import tw.nekomimi.nekogram.utils.PopupBuilder;
@SuppressLint("RtlHardcoded")
@ -245,13 +246,14 @@ public class NekoSettingsActivity extends BaseFragment {
PopupBuilder builder = new PopupBuilder(view);
builder.setItemsIndexed(new String[]{
builder.setItems(new String[]{
LocaleController.getString("MapPreviewProviderTelegram", R.string.MapPreviewProviderTelegram),
LocaleController.getString("MapPreviewProviderYandex", R.string.MapPreviewProviderYandex),
LocaleController.getString("MapPreviewProviderNobody", R.string.MapPreviewProviderNobody)
}, (it) -> {
NekoConfig.setMapPreviewProvider(it);
}, (i, __) -> {
NekoConfig.setMapPreviewProvider(i);
listAdapter.notifyItemChanged(position);
return Unit.INSTANCE;
});
builder.show();
@ -260,12 +262,13 @@ public class NekoSettingsActivity extends BaseFragment {
PopupBuilder builder = new PopupBuilder(view);
builder.setItemsIndexed(new String[]{
builder.setItems(new String[]{
LocaleController.getString("FirstLast", R.string.FirstLast),
LocaleController.getString("LastFirst", R.string.LastFirst)
}, (i) -> {
}, (i, __) -> {
NekoConfig.setNameOrder(i + 1);
listAdapter.notifyItemChanged(position);
return Unit.INSTANCE;
});
builder.show();
@ -274,13 +277,14 @@ public class NekoSettingsActivity extends BaseFragment {
PopupBuilder builder = new PopupBuilder(view);
builder.setItemsIndexed(new String[]{
builder.setItems(new String[]{
LocaleController.getString("DependsOnDate", R.string.DependsOnDate),
LocaleController.getString("Christmas", R.string.Christmas),
LocaleController.getString("Valentine", R.string.Valentine)
}, (i) -> {
}, (i, __) -> {
NekoConfig.setEventType(i);
listAdapter.notifyItemChanged(position);
return Unit.INSTANCE;
});
builder.show();
@ -289,15 +293,17 @@ public class NekoSettingsActivity extends BaseFragment {
PopupBuilder builder = new PopupBuilder(view);
builder.setItemsIndexed(new String[]{
builder.setItems(new String[]{
LocaleController.getString("DependsOnDate", R.string.DependsOnDate),
LocaleController.getString("Snowflakes", R.string.Snowflakes),
LocaleController.getString("Fireworks", R.string.Fireworks)
}, (i) -> {
}, (i, __) -> {
NekoConfig.setActionBarDecoration(i);
listAdapter.notifyItemChanged(position);
return null;
});
builder.show();
@ -404,33 +410,47 @@ public class NekoSettingsActivity extends BaseFragment {
PopupBuilder builder = new PopupBuilder(view);
builder.setItemsIndexed(new String[] {
builder.setItems(new String[]{
LocaleController.getString("ProviderGoogleTranslate", R.string.ProviderGoogleTranslate),
LocaleController.getString("ProviderGoogleTranslateCN", R.string.ProviderGoogleTranslateCN),
LocaleController.getString("ProviderLingocloud", R.string.ProviderLingocloud),
LocaleController.getString("ProviderGoogleTranslateWeb", R.string.ProviderGoogleTranslateWeb),
LocaleController.getString("ProviderGoogleTranslateCNWeb", R.string.ProviderGoogleTranslateCNWeb),
LocaleController.getString("ProviderBaiduFanyiWeb", R.string.ProviderBaiduFanyiWeb)
},(i) -> {
}, (i, __) -> {
int target;
switch (i) {
default: target = 1;break;
case 1: target = 2;break;
case 2: target = 3;break;
case 3: target = -1;break;
case 4: target = -2;break;
case 5: target = -3;break;
default:
target = 1;
break;
case 1:
target = 2;
break;
case 2:
target = 3;
break;
case 8:
target = -1;
break;
case 9:
target = -2;
break;
case 10:
target = -3;
break;
}
NekoConfig.setTranslationProvider(target);
listAdapter.notifyItemChanged(translationProviderRow);
return Unit.INSTANCE;
});
builder.show();
@ -1069,9 +1089,10 @@ public class NekoSettingsActivity extends BaseFragment {
value = LocaleController.getString("ProviderBaiduFanyiWeb", R.string.ProviderBaiduFanyiWeb);
break;
case 3:
default:
value = LocaleController.getString("ProviderLingocloud", R.string.ProviderLingocloud);
break;
default:
value = "Unknown";
}
textCell.setTextAndValue(LocaleController.getString("TranslationProvider", R.string.TranslationProvider), value, false);
}

View File

@ -43,6 +43,7 @@ import org.telegram.ui.Components.LayoutHelper;
import java.util.ArrayList;
import kotlin.Unit;
import tw.nekomimi.nekogram.utils.PopupBuilder;
import tw.nekomimi.nekogram.utils.StrUtil;
@ -309,7 +310,13 @@ public class ShadowsocksRSettingsActivity extends BaseFragment {
PopupBuilder select = new PopupBuilder(v);
select.setItems(ShadowsocksRLoader.Companion.getMethods(), methodField.getValueTextView()::setText);
select.setItems(ShadowsocksRLoader.Companion.getMethods(), (__,value) -> {
methodField.getValueTextView().setText(value);
return Unit.INSTANCE;
});
select.show();
@ -327,7 +334,13 @@ public class ShadowsocksRSettingsActivity extends BaseFragment {
PopupBuilder select = new PopupBuilder(v);
select.setItems(ShadowsocksRLoader.Companion.getProtocols(), protocolField.getValueTextView()::setText);
select.setItems(ShadowsocksRLoader.Companion.getProtocols(), (__,value) -> {
protocolField.getValueTextView().setText(value);
return Unit.INSTANCE;
});
select.show();
@ -347,7 +360,13 @@ public class ShadowsocksRSettingsActivity extends BaseFragment {
PopupBuilder select = new PopupBuilder(v);
select.setItems(ShadowsocksRLoader.Companion.getObfses(), obfsField.getValueTextView()::setText);
select.setItems(ShadowsocksRLoader.Companion.getObfses(), (__,value) -> {
obfsField.getValueTextView().setText(value);
return Unit.INSTANCE;
});
select.show();

View File

@ -43,6 +43,7 @@ import org.telegram.ui.Components.LayoutHelper;
import java.util.ArrayList;
import kotlin.Unit;
import tw.nekomimi.nekogram.utils.PopupBuilder;
import tw.nekomimi.nekogram.utils.StrUtil;
@ -69,8 +70,6 @@ public class ShadowsocksSettingsActivity extends BaseFragment {
private static final int done_button = 1;
private static String[] methodSet = ShadowsocksLoader.Companion.getMethods();
public class TypeCell extends FrameLayout {
private TextView textView;
@ -288,7 +287,13 @@ public class ShadowsocksSettingsActivity extends BaseFragment {
PopupBuilder select = new PopupBuilder(v);
select.setItems(methodSet, methodField.getValueTextView()::setText);
select.setItems(ShadowsocksLoader.Companion.getMethods(),(__,value) -> {
methodField.getValueTextView().setText(value);
return Unit.INSTANCE;
});
select.show();

View File

@ -47,6 +47,7 @@ import org.telegram.ui.Components.LayoutHelper;
import java.util.ArrayList;
import kotlin.Unit;
import tw.nekomimi.nekogram.utils.PopupBuilder;
import tw.nekomimi.nekogram.utils.StrUtil;
@ -336,7 +337,13 @@ public class VmessSettingsActivity extends BaseFragment {
PopupBuilder select = new PopupBuilder(v);
select.setItems(securitySet, securityField.getValueTextView()::setText);
select.setItems(securitySet, (__,value) -> {
securityField.getValueTextView().setText(value);
return Unit.INSTANCE;
});
select.show();
@ -354,7 +361,13 @@ public class VmessSettingsActivity extends BaseFragment {
PopupBuilder select = new PopupBuilder(v);
select.setItems(networkSet, networkField.getValueTextView()::setText);
select.setItems(networkSet, (__,value) -> {
networkField.getValueTextView().setText(value);
return Unit.INSTANCE;
});
select.show();
@ -372,7 +385,13 @@ public class VmessSettingsActivity extends BaseFragment {
PopupBuilder select = new PopupBuilder(v);
select.setItems(headTypeSet, headTypeField.getValueTextView()::setText);
select.setItems(headTypeSet, (__,value) -> {
headTypeField.getValueTextView().setText(value);
return Unit.INSTANCE;
});
select.show();

View File

@ -4,7 +4,6 @@ import android.content.SharedPreferences
import org.dizitart.no2.*
import org.dizitart.no2.filters.Filters
import org.telegram.messenger.FileLog
import tw.nekomimi.nekogram.utils.UIUtil
class DbPref(val connection: NitriteCollection) : SharedPreferences {
@ -28,7 +27,7 @@ class DbPref(val connection: NitriteCollection) : SharedPreferences {
}
override fun contains(key: String): Boolean {
return connection.find(Filters.eq("key", key)).hasMore()
return connection.find(Filters.eq("key", key)).count() > 0
}
override fun getBoolean(key: String, defValue: Boolean) = getAs(key, defValue)
@ -65,9 +64,9 @@ class DbPref(val connection: NitriteCollection) : SharedPreferences {
inner class PrefEditor : SharedPreferences.Editor {
var clear = false
val toRemove = HashSet<String>()
val toApply = HashMap<String, Any?>()
private var clear = false
private val toRemove = HashSet<String>()
private val toApply = HashMap<String, Any?>()
override fun clear(): PrefEditor {
clear = true
@ -137,9 +136,7 @@ class DbPref(val connection: NitriteCollection) : SharedPreferences {
}
override fun apply() {
UIUtil.runOnIoDispatcher(Runnable {
commit()
})
commit()
}
}

View File

@ -1,162 +0,0 @@
package tw.nekomimi.nekogram.translator;
import android.text.TextUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONTokener;
import org.telegram.messenger.FileLog;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import tw.nekomimi.nekogram.NekoConfig;
public class GoogleWebTranslator extends Translator {
private static GoogleWebTranslator instance;
private List<String> targetLanguages = Arrays.asList(
"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");
private long[] tkk;
static GoogleWebTranslator getInstance() {
if (instance == null) {
synchronized (GoogleWebTranslator.class) {
if (instance == null) {
instance = new GoogleWebTranslator();
}
}
}
return instance;
}
@Override
protected String translate(String query, String tl) {
String result = translateImpl(query, tl);
if (result == null) {
tkk = null;
return translateImpl(query, tl);
}
return result;
}
@Override
protected List<String> getTargetLanguages() {
return targetLanguages;
}
private String translateImpl(String query, String tl) {
if (tkk == null) {
initTkk();
}
if (tkk == null) {
return null;
}
String tk = Utils.signWeb(query, tkk[0], tkk[1]);
String url = "https://translate.google." + (NekoConfig.translationProvider == 2 ? "cn" : "com") + "/translate_a/single?client=webapp&dt=t&sl=auto" +
"&tl=" + tl +
"&tk=" + tk +
"&q=" + Utils.encodeURIComponent(query); // 不能用URLEncoder
String response = request(url);
if (TextUtils.isEmpty(response)) {
return null;
}
try {
return getResult(response);
} catch (JSONException e) {
FileLog.e(response + e);
return null;
}
}
private String getResult(String string) throws JSONException {
StringBuilder sb = new StringBuilder();
JSONArray array = new JSONArray(new JSONTokener(string)).getJSONArray(0);
for (int i = 0; i < array.length(); i++) {
sb.append(array.getJSONArray(i).getString(0));
}
return sb.toString();
}
private void initTkk() {
String response = request("https://translate.google." + (NekoConfig.translationProvider == 2 ? "cn" : "com"));
if (TextUtils.isEmpty(response)) {
FileLog.e("Tkk init failed");
return;
}
tkk = matchTKK(response);
if (tkk == null) {
FileLog.e("Tkk init failed");
}
}
private long[] matchTKK(String src) {
Matcher matcher = Pattern.compile("tkk\\s*[:=]\\s*['\"]([0-9]+)\\.([0-9]+)['\"]",
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE).matcher(src);
if (matcher.find()) {
if (matcher.group(1) == null || matcher.group(2) == null) {
return null;
}
//noinspection ConstantConditions
return new long[]{Long.parseLong(matcher.group(1)), Long.parseLong(matcher.group(2))};
}
return null;
}
private String request(String url) {
try {
ByteArrayOutputStream outbuf;
InputStream httpConnectionStream;
URL downloadUrl = new URL(url);
URLConnection httpConnection = downloadUrl.openConnection();
httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1");
httpConnection.setConnectTimeout(1000);
httpConnection.setReadTimeout(2000);
httpConnection.connect();
httpConnectionStream = httpConnection.getInputStream();
outbuf = new ByteArrayOutputStream();
byte[] data = new byte[1024 * 32];
while (true) {
int read = httpConnectionStream.read(data);
if (read > 0) {
outbuf.write(data, 0, read);
} else if (read == -1) {
break;
} else {
break;
}
}
String result = new String(outbuf.toByteArray());
try {
httpConnectionStream.close();
} catch (Throwable e) {
FileLog.e(e);
}
try {
outbuf.close();
} catch (Exception ignore) {
}
return result;
} catch (Throwable e) {
FileLog.e(e);
return null;
}
}
}

View File

@ -1,155 +0,0 @@
package tw.nekomimi.nekogram.translator;
import android.text.TextUtils;
import androidx.annotation.Keep;
import com.google.gson.Gson;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import org.telegram.messenger.FileLog;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
public class LingoTranslator extends Translator {
private static LingoTranslator instance;
private List<String> targetLanguages = Arrays.asList("zh", "en", "es", "fr", "ja", "ru");
static LingoTranslator getInstance() {
if (instance == null) {
synchronized (LingoTranslator.class) {
if (instance == null) {
instance = new LingoTranslator();
}
}
}
return instance;
}
@Override
protected List<String> getTargetLanguages() {
return targetLanguages;
}
@Override
protected String translate(String query, String tl) {
LingoRequest params = new LingoRequest(query, "auto2" + tl);
Gson gson = new Gson();
String response = request(gson.toJson(params));
if (TextUtils.isEmpty(response)) {
return null;
}
try {
LingoResponse lingoResponse = gson.fromJson(response, LingoResponse.class);
if (TextUtils.isEmpty(lingoResponse.target)) {
FileLog.e(response);
return null;
}
return lingoResponse.target;
} catch (Exception e) {
FileLog.e(response + e);
return null;
}
}
private String request(String param) {
try {
ByteArrayOutputStream outbuf;
InputStream httpConnectionStream;
URL downloadUrl = new URL("https://api.interpreter.caiyunai.com/v1/translator");
HttpURLConnection httpConnection = (HttpURLConnection) downloadUrl.openConnection();
httpConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
httpConnection.addRequestProperty("X-Authorization", "token 9sdftiq37bnv410eon2l");//白嫖
httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1");
httpConnection.setConnectTimeout(1000);
httpConnection.setReadTimeout(2000);
httpConnection.setRequestMethod("POST");
httpConnection.setDoOutput(true);
DataOutputStream dataOutputStream = new DataOutputStream(httpConnection.getOutputStream());
//noinspection CharsetObjectCanBeUsed
byte[] t = param.getBytes("UTF-8");
dataOutputStream.write(t);
dataOutputStream.flush();
dataOutputStream.close();
httpConnection.connect();
if (httpConnection.getResponseCode() != HttpURLConnection.HTTP_OK) {
httpConnectionStream = httpConnection.getErrorStream();
} else {
httpConnectionStream = httpConnection.getInputStream();
}
outbuf = new ByteArrayOutputStream();
byte[] data = new byte[1024 * 32];
while (true) {
int read = httpConnectionStream.read(data);
if (read > 0) {
outbuf.write(data, 0, read);
} else if (read == -1) {
break;
} else {
break;
}
}
String result = new String(outbuf.toByteArray());
try {
httpConnectionStream.close();
} catch (Throwable e) {
FileLog.e(e);
}
try {
outbuf.close();
} catch (Exception ignore) {
}
return result;
} catch (Throwable e) {
FileLog.e(e);
return null;
}
}
public static class LingoRequest {
@SerializedName("source")
@Expose
@Keep
public String source;
@SerializedName("trans_type")
@Expose
@Keep
String transType;
@SerializedName("request_id")
@Expose
@Keep
String requestId;
@SerializedName("detect")
@Expose
@Keep
Boolean detect;
LingoRequest(String source, String transType) {
super();
this.source = source;
this.transType = transType;
this.requestId = String.valueOf(System.currentTimeMillis());
this.detect = true;
}
}
static class LingoResponse {
@SerializedName("target")
@Expose
String target;
}
}

View File

@ -1,102 +0,0 @@
package tw.nekomimi.nekogram.translator;
import android.annotation.SuppressLint;
import android.os.AsyncTask;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import tw.nekomimi.nekogram.NekoConfig;
abstract public class Translator {
public static void translate(String query, TranslateCallBack translateCallBack) {
Locale locale = LocaleController.getInstance().currentLocale;
String toLang;
if (NekoConfig.translationProvider != 3 && locale.getLanguage().equals("zh") && (locale.getCountry().toUpperCase().equals("CN") || locale.getCountry().toUpperCase().equals("TW"))) {
toLang = locale.getLanguage() + "-" + locale.getCountry().toUpperCase();
} else {
toLang = locale.getLanguage();
}
Translator translator = NekoConfig.translationProvider == 3 ? LingoTranslator.getInstance() : GoogleWebTranslator.getInstance();
if (!translator.getTargetLanguages().contains(toLang)) {
translateCallBack.onUnsupported();
} else {
translator.startTask(query, toLang, translateCallBack);
}
}
public static String translateSync(String query) throws IOException {
Locale locale = LocaleController.getInstance().currentLocale;
String toLang;
if (NekoConfig.translationProvider != 3 && locale.getLanguage().equals("zh") && (locale.getCountry().toUpperCase().equals("CN") || locale.getCountry().toUpperCase().equals("TW"))) {
toLang = locale.getLanguage() + "-" + locale.getCountry().toUpperCase();
} else {
toLang = locale.getLanguage();
}
Translator translator = NekoConfig.translationProvider == 3 ? LingoTranslator.getInstance() : GoogleWebTranslator.getInstance();
if (!translator.getTargetLanguages().contains(toLang)) {
throw new IOException(LocaleController.getString("TranslateApiUnsupported", R.string.TranslateApiUnsupported));
} else {
try {
String result = translator.translate(query, toLang);
if (result == null) {
throw new RuntimeException();
}
return result;
} catch (Exception ex) {
throw new IOException(LocaleController.getString("TranslateFailed", R.string.TranslateFailed));
}
}
}
private void startTask(String query, String toLang, TranslateCallBack translateCallBack) {
new MyAsyncTask().request(query, toLang, translateCallBack).execute();
}
abstract protected String translate(String query, String tl);
abstract protected List<String> getTargetLanguages();
public interface TranslateCallBack {
void onSuccess(String translation);
void onError();
void onUnsupported();
}
@SuppressLint("StaticFieldLeak")
private class MyAsyncTask extends AsyncTask<Void, Integer, String> {
TranslateCallBack translateCallBack;
String query;
String tl;
public MyAsyncTask request(String query, String tl, TranslateCallBack translateCallBack) {
this.query = query;
this.tl = tl;
this.translateCallBack = translateCallBack;
return this;
}
@Override
protected String doInBackground(Void... params) {
return translate(query, tl);
}
@Override
protected void onPostExecute(String result) {
if (result == null) {
translateCallBack.onError();
} else {
translateCallBack.onSuccess(result);
}
}
}
}

View File

@ -1,4 +1,4 @@
package tw.nekomimi.nekogram.translator;
package tw.nekomimi.nekogram.transtale;
import org.dizitart.no2.Document;
import org.dizitart.no2.IndexType;

View File

@ -1,4 +1,4 @@
package tw.nekomimi.nekogram.translator;
package tw.nekomimi.nekogram.transtale;
import java.nio.charset.Charset;
import java.util.ArrayList;
@ -7,9 +7,9 @@ import java.util.List;
/**
* @author Bin
*/
class Utils {
public class TransUtils {
static String signWeb(String text, long key1, long key2) {
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);
@ -56,7 +56,7 @@ class Utils {
return r;
}
static String encodeURIComponent(String str) {
public static String encodeURIComponent(String str) {
if (str == null) return null;
byte[] bytes = str.getBytes(Charset.defaultCharset());

View File

@ -1,4 +1,4 @@
package tw.nekomimi.nekogram.translator;
package tw.nekomimi.nekogram.transtale;
import android.annotation.SuppressLint;
import android.app.Activity;
@ -62,7 +62,7 @@ public class TranslateBottomSheet extends BottomSheet {
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", Utils.encodeURIComponent(text));
url = String.format("https://fanyi.baidu.com/?aldtype=38319&tpltype=sigma#auto/zh/%s", TransUtils.encodeURIComponent(text));
break;
}
} catch (UnsupportedEncodingException e) {

View File

@ -1,18 +1,18 @@
package tw.nekomimi.nekogram.translator
package tw.nekomimi.nekogram.transtale
import org.dizitart.no2.filters.Filters
import org.dizitart.no2.objects.filters.ObjectFilters
import tw.nekomimi.nekogram.database.mkCacheDatabase
object TranslateDb {
val db = mkCacheDatabase("translate_caches")
var conn = db.getRepository("trans",TransItem::class.java)
var conn = db.getRepository("trans", TransItem::class.java)
@JvmStatic
fun clear() {
conn.drop()
conn = db.getRepository("trans",TransItem::class.java)
conn.remove(ObjectFilters.ALL)
}

View File

@ -0,0 +1,80 @@
package tw.nekomimi.nekogram.transtale
import org.telegram.messenger.FileLog
import org.telegram.messenger.LocaleController
import tw.nekomimi.nekogram.NekoConfig
import tw.nekomimi.nekogram.transtale.source.*
import tw.nekomimi.nekogram.utils.UIUtil
import java.util.*
interface Translator {
fun doTranslate(from: String, to: String, query: String): String
companion object {
@Throws(Exception::class)
@JvmStatic
@JvmOverloads
fun translate(to: Locale = LocaleController.getInstance().currentLocale, query: String): String {
var toLang = to.language
if (NekoConfig.translationProvider < 3) {
if (to.language == "zh" && (to.country.toUpperCase() == "CN" || to.country.toUpperCase() == "TW")) {
toLang = to.language + "-" + to.country.toUpperCase()
} else if (to.language == "pt" && to.country in arrayOf("PT","BR")) {
toLang = to.language + "-" + to.country.toUpperCase()
}
}
val translator = when (NekoConfig.translationProvider) {
in 1..2 -> GoogleWebTranslator
3 -> LingoTranslator
else -> throw IllegalArgumentException()
}
// FileLog.d("[Trans] use provider ${translator.javaClass.simpleName}, toLang: $toLang, query: $query")
return translator.doTranslate("auto", toLang, query)
}
@JvmStatic
@JvmOverloads
fun translate(to: Locale = 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,78 @@
package tw.nekomimi.nekogram.transtale.source
import android.text.TextUtils
import okhttp3.Request
import org.telegram.messenger.LocaleController
import org.telegram.messenger.R
import tw.nekomimi.nekogram.NekoConfig
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.lang.UnsupportedOperationException
import java.util.regex.Pattern
object GoogleWebTranslator : Translator {
lateinit var tkk: LongArray
override fun doTranslate(from: String, to: String, query: String): String {
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 = HttpUtil.okHttpClient
.newCall(Request.Builder()
.url(url)
.applyUserAgent()
.build()).execute()
if (response.code != 200) {
error("HTTP ${response.code} : ${response.body?.string()}")
}
return response.body!!.string()
}
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,46 @@
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 response = HttpUtil.okHttpClient.newCall(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()).execute()
if (response.code != 200) {
error("HTTP ${response.code} : ${response.body?.string()}")
}
return JSONObject(response.body!!.string()).getString("target")
}
}

View File

@ -10,6 +10,8 @@ import org.telegram.messenger.LocaleController
import org.telegram.messenger.R
import org.telegram.ui.ActionBar.AlertDialog
import org.telegram.ui.ActionBar.Theme
import tw.nekomimi.nekogram.NekoConfig
import java.util.concurrent.atomic.AtomicReference
object AlertUtil {
@ -58,4 +60,78 @@ object AlertUtil {
})
@JvmStatic
fun showTransFailedDialog(ctx: Context, noRetry: Boolean, message: String, retryRunnable: Runnable) = UIUtil.runOnUIThread(Runnable {
ctx.setTheme(R.style.Theme_TMessages)
val builder = AlertDialog.Builder(ctx)
builder.setTitle(LocaleController.getString("TranslateFailed", R.string.TranslateFailed))
builder.setMessage(message)
val reference = AtomicReference<AlertDialog>()
builder.setNeutralButton(LocaleController.getString("ChangeTranslateProvider", R.string.ChangeTranslateProvider)) {
_, _ ->
val view = reference.get().getButton(AlertDialog.BUTTON_NEUTRAL)
val popup = PopupBuilder(view, true)
popup.setItems(arrayOf(
LocaleController.getString("ProviderGoogleTranslate", R.string.ProviderGoogleTranslate),
LocaleController.getString("ProviderGoogleTranslateCN", R.string.ProviderGoogleTranslateCN),
LocaleController.getString("ProviderLingocloud", R.string.ProviderLingocloud)
)) { item, _ ->
reference.get().dismiss()
NekoConfig.setTranslationProvider(item + 1)
retryRunnable.run()
}
popup.show()
}
if (noRetry) {
builder.setPositiveButton(LocaleController.getString("Cancel", R.string.Cancel)) { _, _ ->
reference.get().dismiss()
}
} else {
builder.setPositiveButton(LocaleController.getString("Retry", R.string.Retry)) { _, _ ->
reference.get().dismiss()
retryRunnable.run()
}
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel)) { _, _ ->
reference.get().dismiss()
}
}
reference.set(builder.create().apply {
setDismissDialogByButtons(false)
show()
})
})
}

View File

@ -33,7 +33,7 @@ open class DnsFactory {
fun addProvider(url: String) {
providers.add(DnsOverHttps.Builder()
.client(HttpUtil.okhttpClient)
.client(HttpUtil.okHttpClient)
.url(url.toHttpUrl())
.includeIPv6(ConnectionsManager.useIpv6Address())
.build())

View File

@ -7,34 +7,46 @@ import java.net.InetSocketAddress
import java.net.Proxy
import java.util.concurrent.TimeUnit
fun Request.Builder.applyUserAgent(): Request.Builder {
header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1")
header("X-Requested-With", "XMLHttpRequest")
return this
}
object HttpUtil {
@JvmField
val okhttpClient = OkHttpClient().newBuilder().readTimeout(500,TimeUnit.MILLISECONDS).build()
val okHttpClient = OkHttpClient().newBuilder().connectTimeout(5, TimeUnit.SECONDS).build()
@JvmStatic
val okhttpClientWithCurrProxy: OkHttpClient get() {
val okHttpClientWithCurrProxy: OkHttpClient
get() {
return if (!SharedConfig.proxyEnabled || SharedConfig.currentProxy?.secret != null ) {
return if (!SharedConfig.proxyEnabled || SharedConfig.currentProxy?.secret != null) {
okhttpClient
okHttpClient
} else {
} else {
okhttpClient.newBuilder()
.proxy(Proxy(Proxy.Type.SOCKS,InetSocketAddress(SharedConfig.currentProxy.address,SharedConfig.currentProxy.port)))
.build()
okHttpClient.newBuilder()
.proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress(SharedConfig.currentProxy.address, SharedConfig.currentProxy.port)))
.build()
}
}
}
@JvmStatic
fun get(url: String): String {
val request = Request.Builder().url(url).build()
val request = Request.Builder().url(url)
.applyUserAgent()
.build()
okhttpClient.newCall(request).execute().apply {
okHttpClient.newCall(request).execute().apply {
val body = body
@ -44,25 +56,15 @@ object HttpUtil {
}
@JvmStatic
fun get(url: String,ua: String): String {
val request = Request.Builder().url(url).addHeader("User-Agent",ua).build()
okhttpClient.newCall(request).execute().apply {
return body?.string() ?: error("HTTP ERROR $code")
}
}
@JvmStatic
fun getByteArray(url: String): ByteArray {
val request = Request.Builder().url(url).build()
val request = Request.Builder()
.url(url)
.applyUserAgent()
.build()
okhttpClient.newCall(request).execute().apply {
okHttpClient.newCall(request).execute().apply {
return body?.bytes() ?: error("HTTP ERROR $code")

View File

@ -1,27 +1,24 @@
package tw.nekomimi.nekogram.utils
import android.annotation.SuppressLint
import android.view.View
import org.telegram.ui.ActionBar.ActionBarMenuItem
import org.telegram.ui.ActionBar.Theme
class PopupBuilder(anchor: View) : ActionBarMenuItem(anchor.context, null, Theme.ACTION_BAR_WHITE_SELECTOR_COLOR, -0x4c4c4d) {
@SuppressLint("ViewConstructor")
class PopupBuilder @JvmOverloads constructor(anchor: View, dialog: Boolean = false) : ActionBarMenuItem(anchor.context, null, Theme.ACTION_BAR_WHITE_SELECTOR_COLOR, -0x4c4c4d) {
init {
setAnchor(anchor)
isShowOnTop = dialog
isVerticalScrollBarEnabled = true
}
@FunctionalInterface
interface ItemListener {
fun onClick(item: CharSequence)
}
fun setItems(items: Array<CharSequence>, listener: ItemListener) {
fun setItems(items: Array<CharSequence>, listener: (Int,CharSequence) -> Unit) {
removeAllSubItems()
@ -33,32 +30,7 @@ class PopupBuilder(anchor: View) : ActionBarMenuItem(anchor.context, null, Theme
setDelegate {
listener.onClick(items[it])
}
}
@FunctionalInterface
interface IndexedItemListener {
fun onClick(item: Int)
}
fun setItemsIndexed(items: Array<CharSequence>, listener: IndexedItemListener) {
removeAllSubItems()
items.forEachIndexed { i, v ->
addSubItem(i, v)
}
setDelegate {
listener.onClick(it)
listener(it,items[it])
}

View File

@ -1,2 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>
<resources>
<string name="PrivacyNotice">هشدار حریم خصوصی</string>
<string name="PrivacyNoticePhoneVisible">تشخیص داده شده است که شماره تلفن همراه شما برای همه قابل رویت است ، و این ممکن است باعث شود هکرهای تحت کنترل دولت هویت واقعی شما را پیدا کنند ، لطفا آن را خاموش کنید!</string>
<string name="ApplySuggestion">قبول،اعمال کن</string>
<string name="DoNotRemindAgain">دوباره یادآوری نکن</string>
</resources>

View File

@ -1,13 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="NekoXProxy">پروکسی عمومی نکوX</string>
<string name="PublicPrefix">(عمومی)</string>
<string name="NekoXProxyInfo">ممکن است ده ها ثانیه برای بارگیری پروکسی داخلی نکوX طول بکشد</string>
<string name="UseOfficalId">پنهان شده به عنوان برنامه رسمی</string>
<string name="UseOfficalIdNotice">با استفاده از شناسه رسمی برنامه وارد شوید ، اگر قادر به ثبت نام یا ورود به سیستم نیستید ، این ممکن است کمک کند. \ n \ n توجه: اگر از آخرین نسخه استفاده می کنید ، fcm کار نخواهد کرد.</string>
<string name="ChangeTranslateProvider">تغییر ارائه دهنده خدمات</string>
<string name="PrivacyNotice">هشدار حریم خصوصی</string>
<string name="PrivacyNoticePhoneVisible">تشخیص داده شده است که شماره تلفن همراه شما برای همه قابل رویت است ، و این ممکن است باعث شود هکرهای تحت کنترل دولت هویت واقعی شما را پیدا کنند ، لطفا آن را خاموش کنید!</string>
<string name="PrivacyNoticeAddByPhone">تشخیص داده شده است که تنظیمات \" یافتن من از طریق شماره تلفن\" شما خاموش نیست، که ممکن است باعث شود یک هکر تحت کنترل دولت بتواند هویت واقعی شما را پیدا کند ، لطفاً آن را خاموش کنید!</string>
<string name="PrivacyNoticeP2p">تشخیص داده شده است که تنظیمات \"مجاز تماس های نظیر به نظیر\" را خاموش نکرده اید ، که ممکن است باعث شود هکرهای تحت کنترل دولت هویت واقعی شما را پیدا کنند ، لطفاً آن را خاموش کنید!</string>
<string name="ApplySuggestion">قبول،اعمال کن</string>
<string name="DoNotRemindAgain">دیگر یادآوری نشود</string>
<string name="RemoveTitleEmoji">حذف ایموجی کنار اسم Nekogram x</string>
<string name="NekoXProxy">پروکسی عمومی NekoX</string>
<string name="PublicPrefix">[عمومی]</string>
<string name="NekoXProxyInfo">ممکن است چند ثانیه برای بارگیری پروکسی داخلی NekoX طول بکشد :)</string>
<string name="HidePublicProxyList">مخفی کردن لیست پروکسی عمومی</string>
<string name="DisableChatAction">وضعیت مرا ارسال نکن</string>
<string name="FakeScreenshot">تصویر قبل</string>
<string name="EnableDeveloperMode">فعالسازی توسعه دهنده</string>
<string name="DisableDeveloperMode">غیرفعال‌سازی مد توسعه دهنده</string>
<string name="FakeScreenshot">تصویر پیش‌نمایش</string>
<string name="SaveCacheToSdcard">ذخیره کش در حافظه sd card</string>
<string name="FilterNameUsers">کاربران</string>
<string name="FilterNameUsersDescription">فقط پیام های چت های خصوصی</string>
<string name="FilterNameContacts">مخاطبین</string>
<string name="FilterNameContactsDescription">فقط پیام های کاربران ذخیره شده</string>
<string name="FilterNameGroups">گروه ها</string>
<string name="FilterNameGroupsDescription">فقط پیامهای گفتگو های گروهی</string>
<string name="FilterNameChannels">کانال ها</string>
<string name="FilterNameChannelsDescription">فقط پیام های کانال ها</string>
<string name="FilterNameBots">ربات ها</string>
<string name="FilterNameBotsDescription">فقط پیام های ربات ها</string>
<string name="FilterNameUnmuted">صدا دار</string>
<string name="FilterNameUnmutedDescription">فقط پیام های گفتگو های صدا دار</string>
<string name="FilterNameUnread2">خوانده نشده</string>
<string name="FilterNameUnreadDescription">فقط پیام های خوانده نشده</string>
<string name="FilterNameUnmutedAndUnread">صدا دار&amp; خوانده نشده</string>
<string name="FilterNameUnmutedAndUnreadDescription">فقط پیام های خوانده نشده از گفتگو های صدادار</string>
<string name="IgnoreMutedCount">نمایش ندادن شمارشگر چت های خوانده نشده در پوشه ی تب ها</string>
<string name="DialogsSettings">تنظیمات گفتگو</string>
<string name="SortMenu">تنظیمات مرتب سازی گفتگو</string>
<string name="SortByUnread">ترتیب بر اساس خوانده نشده</string>
<string name="SortByUnmuted">ترتیب بر اساس صدادار</string>
<string name="SortByUser">ترتیب بر اساس کاربر</string>
<string name="SortByContacts">ترتیب بر اساس مخاطبین</string>
<string name="NekoXPushService">خدمات NekoX</string>
<string name="EnablePushAlert">لطفا خدمات NekoX را فعال کنید</string>
<string name="DisablePushAlert">لطفا خدمات NekoX رو غیرفعل کنید</string>
<string name="MIUIPermissionNote">برای کاربران MIUI،لطفا دسترسی شروع خودکار را برای دریافت اعلانات NekoX فعال کنید.</string>
<string name="DisableUndo">غیرفعال کردن واگرد</string>
<string name="DisableSystemAccount">غیرفعال کردن حساب کاربری سیستم</string>
<string name="FilterMenu">منوی فیلتر گفتگو ها</string>
<string name="DisableProxyWhenVpnEnabled">غیرفعال کردن پروکسی هنگام فعال کردن VPN</string>
<string name="SkipOpenLinkConfirm">غیرفعال کردن کادر تایید باز شدن لینک</string>
<string name="DeleteAllInChat">حذف همه در این گفتگو</string>
<string name="DeleteAllInChatAlert">هشدار! با این کار ، **تمام پیام ها** در این گفتگو برای همه شرکت کنندگان حذف می شود.</string>
<string name="UnblockAll">رفع مسدودی همه</string>
<string name="UnblockAllWarn">آیا شما از رفع مسدود**همه ی کاربران و ربات ها**اطمینان دارید؟</string>
<string name="BlockedListEmpty">شما هیچ فردی را مسدود نکرده اید :)</string>
<string name="ProxyTypeVmess">پروکسی Vmess</string>
<string name="AddProxySocks5">افزودن پروکسی Socks5</string>
<string name="AddProxyTelegram">افزودن پروکسی MTproto</string>
<string name="AddProxyVmess">افزودن پروکسی Vmess</string>
<string name="AddProxySS">افزودن شادوساکس SS</string>
<string name="AddProxySSR">افزودن شادوساکس SSR</string>
<string name="EditProxy">ویرایش پروکسی</string>
<string name="ShareProxy">اشتراک گذاری پروکسی</string>
<string name="ProxyDelete">حذف پروکسی</string>
<string name="ProxyInfoVmess">تنظیمات پروکسی Vmess</string>
<string name="VmessUserId">آیدی کاربر</string>
<string name="VmessAlterId">آیدی عددی</string>
<string name="VmessSecurity">Security</string>
<string name="VmessNetwork">Network</string>
<string name="VmessHeadType">Head Type</string>
<string name="VmessRequestHost">Request Host / QUIC Security</string>
<string name="VmessPath">Path / QUIC Key</string>
<string name="VmessTls">Use TLS</string>
<string name="ProxyInfoSS">تنظیمات شادوساکس SS</string>
<string name="SSPassword">گذرواژه</string>
<string name="SSMethod">Encrypt Method</string>
<string name="ProxyInfoSSR">تنظیمات پروکسی شادوساکس SSR</string>
<string name="SSRProtocol">Protocol</string>
<string name="SSRProtocolParams">Protocol Params</string>
<string name="SSRObfs">Obfs</string>
<string name="SSRObfsParam">Obfs Param</string>
<string name="ProxyRemarks">ملاحظات</string>
<string name="RetestPing">تست مجدد پینگ تمامی سرورها</string>
<string name="ReorderByPing">مرتب سازی پروکسی ها براساس پینگ</string>
<string name="ExportProxies">اکسپورت سرورها بصورت فایل</string>
<string name="ImportProxies">ایمپورت فایل سرورها</string>
<string name="ImportProxyList">ایمپورت سرورهای پروکسی</string>
<string name="ImportProxyListConfirm">آیا شما از**حذف تمامی سرور ها**اطمینان دارید؟</string>
<string name="InvalidProxyFile">لیست پروکسی نامعتبر: </string>
<string name="ImportedProxies">سرور های پروکسی واردشده: </string>
<string name="ErrorsInImport">مشکل در وارد کردن فایل: </string>
<string name="NoProxy">شما هیچ سرور پروکسی اضافه نکرده اید.</string>
<string name="DeleteAllServer">حذف تمامی سرور ها</string>
<string name="DeleteUnavailableServer">حذف سرور های غیرقابل دسترس</string>
<string name="DeleteAllServerConfirm">آیا شما از**حذف تمامی سرور ها**اطمینان دارید؟</string>
<string name="DeleteUnavailableServerConfirm">آیا شما از**حذف تمامی سرور های غیرقابل دسترس**اطمینان دارید؟</string>
<string name="MinApi21Required">متأسفیم ، حداقل به Android 5 نیاز دارید.</string>
<string name="ImportProxyFromClipboard">وارد کردن از کلیپ بورد</string>
<string name="BrokenLink">لینک خراب/ناشناس</string>
<string name="ShareQRCode">کد QR</string>
<string name="ScanQRCode">اسکن کد QR</string>
<string name="NoQrFound">هیچ کد QR یافت نشد</string>
<string name="EnableDeveloperMode">فعالسازی حالت توسعه دهنده</string>
<string name="DisableDeveloperMode">غیرفعال‌سازی حالت توسعه دهنده</string>
<string name="DeveloperSettings">تنظیمات توسعه دهنده</string>
<string name="DisableFlagSecure">غیرفعال‌سازی پرچم امنیتی</string>
<string name="DisableScreenshotDetection">عدم شناسایی اسکرین‌شات</string>
<string name="DisableScreenshotDetection">غیر فعال کردن شناسایی اسکرین‌شات</string>
<string name="LoginSettings">تنظیمات ورود به سیستم</string>
<string name="ShowTestBackend">نمایش آزمایشی پس زمینه</string>
<string name="ShowBotLogin">دیدن ربات وارد شده</string>
<string name="NekoXFaq">پرسش های متداول NekoX</string>
</resources>

View File

@ -6,6 +6,8 @@
<string name="UseOfficalId">Disguised as official app</string>
<string name="UseOfficalIdNotice">Log in using the official App Id, if you are unable to register or log in, this may help.\n\nNote: fcm will not work if you are using the release version.</string>
<string name="ChangeTranslateProvider">Change Provider</string>
<string name="PrivacyNotice">Privacy warning</string>
<string name="PrivacyNoticePhoneVisible">It is detected that your mobile phone number is visible to anyone, which may cause government-controlled hackers to find your true identity, please turn it off!</string>
<string name="PrivacyNoticeAddByPhone">It is detected that you are not turned off the \"Allow find me through phone number\" Setting, which may cause a government-controlled hacker to find your true identity, please turn it off!</string>