mirror of https://github.com/NekoX-Dev/NekoX.git
Styles
This commit is contained in:
parent
603f6dc0e9
commit
77b6fe7eff
|
@ -16,9 +16,9 @@ import android.content.pm.PackageManager;
|
|||
@SuppressWarnings("ConstantConditions")
|
||||
public class BuildVars {
|
||||
|
||||
public static boolean DEBUG_VERSION = false;
|
||||
public static boolean DEBUG_PRIVATE_VERSION = false;
|
||||
public static boolean LOGS_ENABLED = false;
|
||||
public static boolean DEBUG_VERSION = BuildConfig.BUILD_TYPE.equals("debug");
|
||||
public static boolean DEBUG_PRIVATE_VERSION = DEBUG_VERSION;
|
||||
public static boolean LOGS_ENABLED;
|
||||
public static boolean USE_CLOUD_STRINGS = true;
|
||||
|
||||
public static int BUILD_VERSION;
|
||||
|
@ -46,7 +46,7 @@ public class BuildVars {
|
|||
|
||||
if (ApplicationLoader.applicationContext != null) {
|
||||
SharedPreferences sharedPreferences = ApplicationLoader.applicationContext.getSharedPreferences("systemConfig", Context.MODE_PRIVATE);
|
||||
LOGS_ENABLED = sharedPreferences.getBoolean("logsEnabled", DEBUG_VERSION);
|
||||
LOGS_ENABLED = sharedPreferences.getBoolean("logsEnabled", LOGS_ENABLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,9 +47,6 @@ public class FileLog {
|
|||
}
|
||||
|
||||
public static void e(final Throwable e) {
|
||||
if (!BuildVars.LOGS_ENABLED) {
|
||||
return;
|
||||
}
|
||||
Log.e(mkTag(),mkMessage(e),e);
|
||||
}
|
||||
|
||||
|
|
|
@ -526,11 +526,11 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
|||
AlertUtil.showToast(LocaleController.getString("TextCopied", R.string.TextCopied));
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
builder.addItem(BuildVars.DEBUG_VERSION ? LocaleController.getString("DebugMenuDisableLogs", R.string.DebugMenuDisableLogs) : LocaleController.getString("DebugMenuEnableLogs", R.string.DebugMenuEnableLogs), R.drawable.baseline_bug_report_24, (it) -> {
|
||||
builder.addItem(BuildVars.LOGS_ENABLED ? LocaleController.getString("DebugMenuDisableLogs", R.string.DebugMenuDisableLogs) : LocaleController.getString("DebugMenuEnableLogs", R.string.DebugMenuEnableLogs), R.drawable.baseline_bug_report_24, (it) -> {
|
||||
builder.dismiss();
|
||||
BuildVars.DEBUG_VERSION = !BuildVars.DEBUG_VERSION;
|
||||
BuildVars.LOGS_ENABLED = !BuildVars.LOGS_ENABLED;
|
||||
SharedPreferences sharedPreferences = ApplicationLoader.applicationContext.getSharedPreferences("systemConfig", Context.MODE_PRIVATE);
|
||||
sharedPreferences.edit().putBoolean("logsEnabled", BuildVars.DEBUG_VERSION).apply();
|
||||
sharedPreferences.edit().putBoolean("logsEnabled", BuildVars.LOGS_ENABLED).apply();
|
||||
updateRows();
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
|
|
|
@ -204,8 +204,8 @@ public class NekoConfig {
|
|||
askBeforeCall = preferences.getBoolean("askBeforeCall", false);
|
||||
disableNumberRounding = preferences.getBoolean("disableNumberRounding", false);
|
||||
|
||||
hideProxyByDefault = preferences.getBoolean("hide_proxy_by_default", BuildVars.isMini);
|
||||
useProxyItem = preferences.getBoolean("use_proxy_item",false);
|
||||
hideProxyByDefault = preferences.getBoolean("hide_proxy_by_default", false);
|
||||
useProxyItem = preferences.getBoolean("use_proxy_item", true);
|
||||
|
||||
disableAppBarShadow = preferences.getBoolean("disableAppBarShadow", false);
|
||||
mediaPreview = preferences.getBoolean("mediaPreview", false);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package tw.nekomimi.nekogram.utils
|
||||
package tw.nekomimi.nekogram
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.View
|
|
@ -8,9 +8,7 @@
|
|||
|
||||
package tw.nekomimi.nekogram;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
|
@ -22,24 +20,16 @@ import android.view.Gravity;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.github.shadowsocks.plugin.PluginConfiguration;
|
||||
import com.github.shadowsocks.plugin.PluginContract;
|
||||
import com.github.shadowsocks.plugin.PluginList;
|
||||
import com.github.shadowsocks.plugin.PluginManager;
|
||||
import com.github.shadowsocks.plugin.PluginOptions;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||
import org.telegram.ui.ActionBar.BaseFragment;
|
||||
|
@ -47,16 +37,12 @@ import org.telegram.ui.ActionBar.Theme;
|
|||
import org.telegram.ui.ActionBar.ThemeDescription;
|
||||
import org.telegram.ui.Cells.TextCheckCell;
|
||||
import org.telegram.ui.Cells.TextInfoPrivacyCell;
|
||||
import org.telegram.ui.Cells.TextSettingsCell;
|
||||
import org.telegram.ui.Components.EditTextBoldCursor;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.PopupBuilder;
|
||||
|
||||
public class RelayBatonSettingsActivity extends BaseFragment {
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ import java.util.ArrayList;
|
|||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.utils.PopupBuilder;
|
||||
|
||||
public class ShadowsocksRSettingsActivity extends BaseFragment {
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ import java.util.ArrayList;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
import tw.nekomimi.nekogram.utils.PopupBuilder;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public class ShadowsocksSettingsActivity extends BaseFragment {
|
||||
|
|
|
@ -49,7 +49,6 @@ import java.util.ArrayList;
|
|||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.utils.PopupBuilder;
|
||||
|
||||
public class VmessSettingsActivity extends BaseFragment {
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.telegram.ui.ActionBar.ThemeDescription;
|
|||
import org.telegram.ui.Cells.EmptyCell;
|
||||
import org.telegram.ui.Cells.HeaderCell;
|
||||
import org.telegram.ui.Cells.NotificationsCheckCell;
|
||||
import org.telegram.ui.Cells.RadioColorCell;
|
||||
import org.telegram.ui.Cells.ShadowSectionCell;
|
||||
import org.telegram.ui.Cells.TextCheckCell;
|
||||
import org.telegram.ui.Cells.TextDetailSettingsCell;
|
||||
|
@ -43,7 +42,7 @@ import java.util.ArrayList;
|
|||
import kotlin.Unit;
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.NekoXConfig;
|
||||
import tw.nekomimi.nekogram.utils.PopupBuilder;
|
||||
import tw.nekomimi.nekogram.PopupBuilder;
|
||||
|
||||
@SuppressLint("RtlHardcoded")
|
||||
public class NekoChatSettingsActivity extends BaseFragment {
|
||||
|
|
|
@ -51,7 +51,7 @@ import tw.nekomimi.nekogram.NekoConfig;
|
|||
import tw.nekomimi.nekogram.transtale.Translator;
|
||||
import tw.nekomimi.nekogram.transtale.TranslatorKt;
|
||||
import tw.nekomimi.nekogram.utils.EnvUtil;
|
||||
import tw.nekomimi.nekogram.utils.PopupBuilder;
|
||||
import tw.nekomimi.nekogram.PopupBuilder;
|
||||
|
||||
@SuppressLint("RtlHardcoded")
|
||||
public class NekoGeneralSettingsActivity extends BaseFragment {
|
||||
|
|
|
@ -1,151 +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.IOException;
|
||||
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) throws IOException {
|
||||
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) throws IOException {
|
||||
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 == PROVIDER_GOOGLE_CN ? "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() throws IOException {
|
||||
String response = request("https://translate.google." + (NekoConfig.translationProvider == PROVIDER_GOOGLE_CN ? "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) throws IOException {
|
||||
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());
|
||||
httpConnectionStream.close();
|
||||
outbuf.close();
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,138 +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.IOException;
|
||||
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) throws IOException {
|
||||
LingoRequest params = new LingoRequest(query, "auto2" + tl);
|
||||
Gson gson = new Gson();
|
||||
String response = request(gson.toJson(params));
|
||||
if (TextUtils.isEmpty(response)) {
|
||||
return null;
|
||||
}
|
||||
LingoResponse lingoResponse = gson.fromJson(response, LingoResponse.class);
|
||||
if (TextUtils.isEmpty(lingoResponse.target)) {
|
||||
FileLog.e(response);
|
||||
return null;
|
||||
}
|
||||
return lingoResponse.target;
|
||||
}
|
||||
|
||||
private String request(String param) throws IOException {
|
||||
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());
|
||||
httpConnectionStream.close();
|
||||
outbuf.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
|
@ -1,211 +0,0 @@
|
|||
package tw.nekomimi.nekogram.translator;
|
||||
|
||||
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 Translator.PROVIDER_GOOGLE_WEB:
|
||||
url = String.format("https://translate.google.com/?view=home&op=translate&text=%s", URLEncoder.encode(text, "UTF-8"));
|
||||
break;
|
||||
case Translator.PROVIDER_GOOGLE_CN_WEB:
|
||||
url = String.format("https://translate.google.cn/?view=home&op=translate&text=%s", URLEncoder.encode(text, "UTF-8"));
|
||||
break;
|
||||
case Translator.PROVIDER_BAIDU_WEB:
|
||||
url = String.format("https://fanyi.baidu.com/?aldtype=38319&tpltype=sigma#auto/zh/%s", Utils.encodeURIComponent(text));
|
||||
break;
|
||||
case Translator.PROVIDER_DEEPL_WEB:
|
||||
url = String.format("https://www.deepl.com/translator#auto/auto/%s", Utils.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();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
package tw.nekomimi.nekogram.translator;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
|
||||
abstract public class Translator {
|
||||
|
||||
public static final int PROVIDER_GOOGLE = 1;
|
||||
public static final int PROVIDER_GOOGLE_CN = 2;
|
||||
public static final int PROVIDER_LINGO = 3;
|
||||
public static final int PROVIDER_YANDEX = 4;
|
||||
public static final int PROVIDER_GOOGLE_WEB = -1;
|
||||
public static final int PROVIDER_GOOGLE_CN_WEB = -2;
|
||||
public static final int PROVIDER_BAIDU_WEB = -3;
|
||||
public static final int PROVIDER_DEEPL_WEB = -4;
|
||||
|
||||
public static void translate(Object query, TranslateCallBack translateCallBack) {
|
||||
Locale locale = LocaleController.getInstance().currentLocale;
|
||||
String toLang;
|
||||
if (NekoConfig.translationProvider != PROVIDER_LINGO && NekoConfig.translationProvider != PROVIDER_YANDEX && 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;
|
||||
switch (NekoConfig.translationProvider) {
|
||||
case PROVIDER_YANDEX:
|
||||
translator = YandexTranslator.getInstance();
|
||||
break;
|
||||
case PROVIDER_GOOGLE:
|
||||
case PROVIDER_GOOGLE_CN:
|
||||
translator = GoogleWebTranslator.getInstance();
|
||||
break;
|
||||
case PROVIDER_LINGO:
|
||||
default:
|
||||
translator = LingoTranslator.getInstance();
|
||||
break;
|
||||
}
|
||||
if (!translator.getTargetLanguages().contains(toLang)) {
|
||||
translateCallBack.onUnsupported();
|
||||
} else {
|
||||
translator.startTask(query, toLang, translateCallBack);
|
||||
}
|
||||
}
|
||||
|
||||
private void startTask(Object query, String toLang, TranslateCallBack translateCallBack) {
|
||||
new MyAsyncTask().request(query, toLang, translateCallBack).execute();
|
||||
}
|
||||
|
||||
abstract protected String translate(String query, String tl) throws IOException, JSONException;
|
||||
|
||||
abstract protected List<String> getTargetLanguages();
|
||||
|
||||
public interface TranslateCallBack {
|
||||
void onSuccess(Object translation);
|
||||
|
||||
void onError(Throwable e);
|
||||
|
||||
void onUnsupported();
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private class MyAsyncTask extends AsyncTask<Void, Integer, Object> {
|
||||
TranslateCallBack translateCallBack;
|
||||
Object query;
|
||||
String tl;
|
||||
|
||||
public MyAsyncTask request(Object query, String tl, TranslateCallBack translateCallBack) {
|
||||
this.query = query;
|
||||
this.tl = tl;
|
||||
this.translateCallBack = translateCallBack;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doInBackground(Void... params) {
|
||||
try {
|
||||
if (query instanceof String) {
|
||||
return translate((String) query, tl);
|
||||
} else if (query instanceof TLRPC.Poll) {
|
||||
TLRPC.TL_poll poll = new TLRPC.TL_poll();
|
||||
TLRPC.TL_poll original = (TLRPC.TL_poll) query;
|
||||
poll.question = original.question +
|
||||
"\n" +
|
||||
"--------" +
|
||||
"\n" + translate(original.question, tl);
|
||||
for (int i = 0; i < original.answers.size(); i++) {
|
||||
TLRPC.TL_pollAnswer answer = new TLRPC.TL_pollAnswer();
|
||||
answer.text = original.answers.get(i).text + " | " + translate(original.answers.get(i).text, tl);
|
||||
answer.option = original.answers.get(i).option;
|
||||
poll.answers.add(answer);
|
||||
}
|
||||
poll.close_date = original.close_date;
|
||||
poll.close_period = original.close_period;
|
||||
poll.closed = original.closed;
|
||||
poll.flags = original.flags;
|
||||
poll.id = original.id;
|
||||
poll.multiple_choice = original.multiple_choice;
|
||||
poll.public_voters = original.public_voters;
|
||||
poll.quiz = original.quiz;
|
||||
return poll;
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported translation query");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Object result) {
|
||||
if (result == null) {
|
||||
translateCallBack.onError(null);
|
||||
} else if (result instanceof Throwable) {
|
||||
translateCallBack.onError((Throwable) result);
|
||||
} else {
|
||||
translateCallBack.onSuccess(result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package tw.nekomimi.nekogram.translator;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Bin
|
||||
*/
|
||||
class Utils {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
package tw.nekomimi.nekogram.translator;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.telegram.messenger.FileLog;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class YandexTranslator extends Translator {
|
||||
|
||||
private static YandexTranslator instance;
|
||||
private List<String> targetLanguages = Arrays.asList(
|
||||
"en", "af", "am", "ar", "az", "be", "bg", "bn", "bs", "ca", "ceb", "cs", "cy",
|
||||
"da", "de", "el", "eo", "es", "et", "eu", "fa", "fi", "fr", "ga", "gd", "gl", "gu",
|
||||
"he", "hi", "hr", "ht", "hu", "hy", "id", "is", "it", "ja", "jv", "ka", "kk", "km",
|
||||
"kn", "ko", "ky", "la", "lb", "lo", "lt", "lv", "mg", "mi", "mk", "ml", "mn", "mr",
|
||||
"ms", "mt", "my", "ne", "nl", "no", "pa", "pl", "pt", "ro", "ru", "si", "sk", "sl",
|
||||
"sq", "sr", "su", "sv", "sw", "ta", "te", "tg", "th", "tl", "tr", "tt", "uk", "ur",
|
||||
"uz", "vi", "xh", "yi", "zh");
|
||||
|
||||
static YandexTranslator getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (YandexTranslator.class) {
|
||||
if (instance == null) {
|
||||
instance = new YandexTranslator();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static String getResult(String string) throws JSONException {
|
||||
JSONObject json = new JSONObject(string);
|
||||
int code = json.getInt("code");
|
||||
if (code != 200) {
|
||||
return null;
|
||||
}
|
||||
JSONArray array = json.getJSONArray("text");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int length = array.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(array.getString(i));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String translate(String query, String tl) throws IOException, JSONException {
|
||||
String result = translateImpl(query, tl);
|
||||
if (result == null) {
|
||||
return translateImpl(query, tl);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTargetLanguages() {
|
||||
return targetLanguages;
|
||||
}
|
||||
|
||||
private String translateImpl(String query, String tl) throws IOException, JSONException {
|
||||
String url = "https://translate.yandex.net/api/v1.5/tr.json/translate"
|
||||
+ "?key=trnsl.1.1.20160205T121943Z.0208eaff12c2747d.9526187390798b3098ec23e8f02073168e0b52c1"
|
||||
+ "&lang=" + tl;
|
||||
return getResult(request(url, "text=" + URLEncoder.encode(query, "UTF-8")));
|
||||
|
||||
}
|
||||
|
||||
private String request(String url, String param) throws IOException {
|
||||
ByteArrayOutputStream outbuf;
|
||||
InputStream httpConnectionStream;
|
||||
URL downloadUrl = new URL(url);
|
||||
HttpURLConnection httpConnection = (HttpURLConnection) downloadUrl.openConnection();
|
||||
httpConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded charset=UTF-8");
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ 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.PopupBuilder
|
||||
import tw.nekomimi.nekogram.utils.UIUtil
|
||||
import tw.nekomimi.nekogram.utils.receive
|
||||
import tw.nekomimi.nekogram.utils.receiveLazy
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.telegram.ui.Components.EditTextBoldCursor
|
|||
import org.telegram.ui.Components.NumberPicker
|
||||
import tw.nekomimi.nekogram.BottomBuilder
|
||||
import tw.nekomimi.nekogram.NekoConfig
|
||||
import tw.nekomimi.nekogram.PopupBuilder
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
|
|
Loading…
Reference in New Issue