mirror of https://github.com/NekoX-Dev/NekoX.git
This commit is contained in:
parent
8832d06e0c
commit
1fa159f440
|
@ -28,6 +28,17 @@ data class AngConfig(
|
|||
var configVersion: Int = 2,
|
||||
var testResult: String = "") {
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return super.equals(other) || (other is VmessBean &&
|
||||
address == other.address &&
|
||||
port == other.port &&
|
||||
id == other.id &&
|
||||
network == other.network &&
|
||||
headerType == other.headerType &&
|
||||
requestHost == other.requestHost &&
|
||||
path == other.path)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
if (configType == V2RayConfig.EConfigType.Vmess) {
|
||||
|
@ -52,7 +63,7 @@ data class AngConfig(
|
|||
|
||||
val remark = "#" + Utils.urlEncode(remarks)
|
||||
|
||||
val url = String.format("%s:%s@%s:%s",security, id, address, port)
|
||||
val url = String.format("%s:%s@%s:%s", security, id, address, port)
|
||||
|
||||
return SS_PROTOCOL + Base64.encodeToString(url.toByteArray(charset("UTF-8")), Base64.NO_WRAP) + remark
|
||||
|
||||
|
|
|
@ -38,15 +38,6 @@ object Utils {
|
|||
* base64 decode
|
||||
*/
|
||||
fun decode(text: String): String {
|
||||
try {
|
||||
return Base64.decode(text, Base64.NO_WRAP).toString(charset("UTF-8"))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
fun decodeUrlSafe(text: String): String {
|
||||
val flags = Base64.NO_PADDING or Base64.URL_SAFE or Base64.NO_WRAP
|
||||
try {
|
||||
return Base64.decode(text, flags).toString(charset("UTF-8"))
|
||||
|
|
|
@ -21,23 +21,20 @@ public class KeepAliveJob extends JobIntentService {
|
|||
private static final Object sync = new Object();
|
||||
|
||||
public static void startJob() {
|
||||
Utilities.globalQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (startingJob || countDownLatch != null) {
|
||||
return;
|
||||
Utilities.globalQueue.postRunnable(() -> {
|
||||
if (startingJob || countDownLatch != null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("starting keep-alive job");
|
||||
}
|
||||
try {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("starting keep-alive job");
|
||||
}
|
||||
synchronized (sync) {
|
||||
startingJob = true;
|
||||
}
|
||||
enqueueWork(ApplicationLoader.applicationContext, KeepAliveJob.class, 1000, new Intent());
|
||||
} catch (Exception ignore) {
|
||||
synchronized (sync) {
|
||||
startingJob = true;
|
||||
}
|
||||
enqueueWork(ApplicationLoader.applicationContext, KeepAliveJob.class, 1000, new Intent());
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2104,7 +2104,7 @@ public class NotificationsController extends BaseController {
|
|||
intent.putExtra("currentAccount", currentAccount);
|
||||
PendingIntent pintent = PendingIntent.getService(ApplicationLoader.applicationContext, 0, intent, 0);
|
||||
SharedPreferences preferences = getAccountInstance().getNotificationsSettings();
|
||||
int minutes = preferences.getInt("repeat_messages", 60);
|
||||
int minutes = preferences.getInt("repeat_messages", 5);
|
||||
if (minutes > 0 && personal_count > 0) {
|
||||
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + minutes * 60 * 1000, pintent);
|
||||
} else {
|
||||
|
|
|
@ -78,4 +78,5 @@ public class NotificationsService extends Service {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ import android.text.TextUtils;
|
|||
import android.util.Base64;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.v2ray.ang.V2RayConfig;
|
||||
import com.v2ray.ang.dto.AngConfig;
|
||||
|
||||
|
@ -27,6 +29,7 @@ import org.json.JSONArray;
|
|||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.telegram.tgnet.ConnectionsManager;
|
||||
import org.telegram.ui.ProxyListActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.RandomAccessFile;
|
||||
|
@ -42,6 +45,7 @@ import tw.nekomimi.nekogram.ProxyManager;
|
|||
import tw.nekomimi.nekogram.ShadowsocksLoader;
|
||||
import tw.nekomimi.nekogram.VmessLoader;
|
||||
import tw.nekomimi.nekogram.utils.FileUtil;
|
||||
import tw.nekomimi.nekogram.utils.ProxyUtil;
|
||||
import tw.nekomimi.nekogram.utils.StrUtil;
|
||||
import tw.nekomimi.nekogram.utils.UIUtil;
|
||||
|
||||
|
@ -187,11 +191,11 @@ public class SharedConfig {
|
|||
|
||||
if (StrUtil.isBlank(remarks)) {
|
||||
|
||||
return "[MTProto] " + address + ":" + port;
|
||||
return "[MTProto] " + address + ":" + port;
|
||||
|
||||
} else {
|
||||
|
||||
return "[MTProto] " + remarks;
|
||||
return "[MTProto] " + remarks;
|
||||
|
||||
}
|
||||
|
||||
|
@ -361,6 +365,22 @@ public class SharedConfig {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
return (address + port).hashCode();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return super.equals(obj) || (
|
||||
obj != null &&
|
||||
obj.getClass().equals(ProxyInfo.class) &&
|
||||
address.equals(((ProxyInfo) obj).address) &&
|
||||
port == ((ProxyInfo) obj).port
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class ExternalSocks5Proxy extends ProxyInfo {
|
||||
|
@ -374,6 +394,8 @@ public class SharedConfig {
|
|||
|
||||
}
|
||||
|
||||
public abstract boolean isStarted();
|
||||
|
||||
public abstract void start();
|
||||
|
||||
public abstract void stop();
|
||||
|
@ -417,16 +439,23 @@ public class SharedConfig {
|
|||
|
||||
if (StrUtil.isBlank(getRemarks())) {
|
||||
|
||||
return "[Vmess] " + bean.getAddress() + ":" + bean.getPort();
|
||||
return "[Vmess] " + bean.getAddress() + ":" + bean.getPort();
|
||||
|
||||
} else {
|
||||
|
||||
return "[Vmess] " + getRemarks();
|
||||
return "[Vmess] " + getRemarks();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStarted() {
|
||||
|
||||
return loader != null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
|
@ -478,6 +507,16 @@ public class SharedConfig {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (bean.getAddress() + bean.getPort() + bean.getId() + bean.getNetwork() + bean.getPath()).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return super.equals(obj) || (obj instanceof VmessProxy && bean.equals(((VmessProxy) obj).bean));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ShadowsocksProxy extends ExternalSocks5Proxy {
|
||||
|
@ -502,16 +541,23 @@ public class SharedConfig {
|
|||
|
||||
if (StrUtil.isBlank(getRemarks())) {
|
||||
|
||||
return "[SS] " + bean.getHost() + ":" + bean.getRemotePort();
|
||||
return "[SS] " + bean.getHost() + ":" + bean.getRemotePort();
|
||||
|
||||
} else {
|
||||
|
||||
return "[SS] " + getRemarks();
|
||||
return "[SS] " + getRemarks();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStarted() {
|
||||
|
||||
return loader != null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
|
@ -564,6 +610,18 @@ public class SharedConfig {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
return (bean.getHost() + bean.getRemotePort() + bean.getMethod()).hashCode();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return super.equals(obj) || (obj instanceof ShadowsocksProxy && bean.equals(((ShadowsocksProxy) obj).bean));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ShadowsocksRProxy extends ExternalSocks5Proxy {
|
||||
|
@ -588,16 +646,22 @@ public class SharedConfig {
|
|||
|
||||
if (StrUtil.isBlank(getRemarks())) {
|
||||
|
||||
return "[SSR] " + bean.getHost() + ":" + bean.getRemotePort();
|
||||
return "[SSR] " + bean.getHost() + ":" + bean.getRemotePort();
|
||||
|
||||
} else {
|
||||
|
||||
return "[SSR] " + getRemarks();
|
||||
return "[SSR] " + getRemarks();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStarted() {
|
||||
|
||||
return loader != null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
|
@ -650,6 +714,18 @@ public class SharedConfig {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
return (bean.getHost() + bean.getRemotePort() + bean.getMethod() + bean.getProtocol() + bean.getProtocol_param() + bean.getObfs() + bean.getObfs_param()).hashCode();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return super.equals(obj) || (obj instanceof ShadowsocksRProxy && bean.equals(((ShadowsocksRProxy) obj).bean));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static LinkedList<ProxyInfo> proxyList = new LinkedList<>();
|
||||
|
@ -1318,12 +1394,19 @@ public class SharedConfig {
|
|||
|
||||
currentProxy = info;
|
||||
|
||||
MessagesController.getGlobalMainSettings().edit().putInt("current_proxy", info.hashCode()).apply();
|
||||
|
||||
saveProxyList();
|
||||
|
||||
setProxyEnable(true);
|
||||
|
||||
}
|
||||
|
||||
public static void reloadProxyList() {
|
||||
proxyListLoaded = false;
|
||||
loadProxyList();
|
||||
}
|
||||
|
||||
public static void loadProxyList() {
|
||||
if (proxyListLoaded) {
|
||||
return;
|
||||
|
@ -1333,8 +1416,72 @@ public class SharedConfig {
|
|||
proxyList.clear();
|
||||
currentProxy = null;
|
||||
|
||||
int current = MessagesController.getGlobalMainSettings().getInt("curent_proxy", 0);
|
||||
|
||||
proxyList.add(publicProxy);
|
||||
|
||||
File remoteProxyListFile = ProxyUtil.cacheFile;
|
||||
|
||||
if (remoteProxyListFile.isFile()) {
|
||||
|
||||
try {
|
||||
|
||||
JSONArray proxyArray = new JSONArray(FileUtil.readUtf8String(remoteProxyListFile));
|
||||
|
||||
for (int a = 0; a < proxyArray.length(); a++) {
|
||||
|
||||
JSONObject proxyObj = proxyArray.getJSONObject(a);
|
||||
|
||||
ProxyInfo info;
|
||||
|
||||
try {
|
||||
|
||||
if (!proxyObj.isNull("proxy")) {
|
||||
|
||||
// old remote protocol
|
||||
|
||||
info = parseProxyInfo(proxyObj.getString("proxy"));
|
||||
|
||||
} else {
|
||||
|
||||
info = ProxyInfo.fromJson(proxyObj);
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
|
||||
FileLog.e("load proxy failed", ex);
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
info.isInternal = true;
|
||||
|
||||
proxyList.add(info);
|
||||
|
||||
if (info.hashCode() == current) {
|
||||
|
||||
currentProxy = info;
|
||||
|
||||
if (info instanceof ExternalSocks5Proxy) {
|
||||
|
||||
((ExternalSocks5Proxy) info).start();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
|
||||
FileLog.e("invalid proxy list json format", ex);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File proxyListFile = new File(ApplicationLoader.applicationContext.getFilesDir().getParentFile(), "nekox/proxy_list.json");
|
||||
|
||||
if (proxyListFile.isFile()) {
|
||||
|
@ -1361,11 +1508,12 @@ public class SharedConfig {
|
|||
|
||||
}
|
||||
|
||||
if (proxyObj.optBoolean("internal", false)) continue;
|
||||
if (!proxyObj.isNull("internal")) continue;
|
||||
if (info.getTitle().toLowerCase().contains("nekox.me")) continue;
|
||||
|
||||
proxyList.add(info);
|
||||
|
||||
if (proxyObj.optBoolean("current", false)) {
|
||||
if (info.hashCode() == current) {
|
||||
|
||||
currentProxy = info;
|
||||
|
||||
|
@ -1517,11 +1665,8 @@ public class SharedConfig {
|
|||
int count = proxyList.size();
|
||||
for (int a = 0; a < count; a++) {
|
||||
ProxyInfo info = proxyList.get(a);
|
||||
try {
|
||||
if (info.toJson().equals(proxyInfo.toJson())) {
|
||||
return info;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
if (info.equals(proxyInfo)) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
proxyList.add(proxyInfo);
|
||||
|
@ -1542,6 +1687,8 @@ public class SharedConfig {
|
|||
|
||||
public static void deleteAllProxy() {
|
||||
|
||||
setProxyEnable(false);
|
||||
|
||||
proxyListLoaded = false;
|
||||
|
||||
proxyList.clear();
|
||||
|
@ -1552,6 +1699,32 @@ public class SharedConfig {
|
|||
|
||||
}
|
||||
|
||||
public static void deleteUnavailableProxy() {
|
||||
|
||||
setProxyEnable(false);
|
||||
|
||||
proxyListLoaded = false;
|
||||
|
||||
Iterator<ProxyInfo> iter = proxyList.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
|
||||
ProxyInfo info = iter.next();
|
||||
|
||||
if (!info.checking && !info.available && info.availableCheckTime != 0) {
|
||||
|
||||
iter.remove();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
saveProxyList();
|
||||
|
||||
loadProxyList();
|
||||
|
||||
}
|
||||
|
||||
public static void checkSaveToGalleryFiles() {
|
||||
try {
|
||||
File telegramPath;
|
||||
|
|
|
@ -14964,7 +14964,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
|
||||
showDialog(builder.create());
|
||||
}
|
||||
} else if (locFile.getName().toLowerCase().endsWith(".nekox.json")) {
|
||||
} else if (locFile.getName().toLowerCase().endsWith(".json")) {
|
||||
|
||||
File finalLocFile = locFile;
|
||||
AlertUtil.showConfirm(getParentActivity(),
|
||||
|
|
|
@ -67,6 +67,8 @@ import java.util.ArrayList;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import tw.nekomimi.nekogram.utils.AlertUtil;
|
||||
|
||||
public class NotificationsSettingsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
public static class NotificationException {
|
||||
|
@ -580,7 +582,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
|
|||
} else if (position == notificationsServiceRow) {
|
||||
if (XiaomiUtilities.isMIUI() && !XiaomiUtilities.isCustomPermissionGranted(XiaomiUtilities.OP_AUTO_START)) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle("Telegram");
|
||||
builder.setTitle(LocaleController.getString("NekoX",R.string.NekoX));
|
||||
builder.setMessage(LocaleController.getString("MIUIPermissionNote",R.string.MIUIPermissionNote));
|
||||
builder.setPositiveButton(LocaleController.getString("OK",R.string.OK),(_x,_y) -> {
|
||||
|
||||
|
@ -594,9 +596,9 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
if (openNotificationListenSettings()) {
|
||||
if (isNotificationListenerEnabled()) {
|
||||
AlertsCreator.showSimpleToast(null, LocaleController.getString("DisablePushAlert", R.string.DisablePushAlert));
|
||||
AlertUtil.showToast( LocaleController.getString("DisablePushAlert", R.string.DisablePushAlert));
|
||||
} else {
|
||||
AlertsCreator.showSimpleToast(null, LocaleController.getString("EnablePushAlert", R.string.EnablePushAlert));
|
||||
AlertUtil.showToast(LocaleController.getString("EnablePushAlert", R.string.EnablePushAlert));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -993,7 +995,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
|
|||
textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("OnlyIfSilent", R.string.OnlyIfSilent), true);
|
||||
}
|
||||
} else if (position == repeatRow) {
|
||||
int minutes = preferences.getInt("repeat_messages", 60);
|
||||
int minutes = preferences.getInt("repeat_messages", 5);
|
||||
String value;
|
||||
if (minutes == 0) {
|
||||
value = LocaleController.getString("RepeatNotificationsNever", R.string.RepeatNotificationsNever);
|
||||
|
|
|
@ -168,9 +168,6 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
|
|||
colorKey = Theme.key_windowBackgroundWhiteBlueText6;
|
||||
if (currentInfo.ping != 0) {
|
||||
valueTextView.setText(LocaleController.getString("Connected", R.string.Connected) + ", " + LocaleController.formatString("Ping", R.string.Ping, currentInfo.ping));
|
||||
} else if (currentInfo.checking) {
|
||||
valueTextView.setText(LocaleController.getString("Connected", R.string.Connected) + ", " + LocaleController.formatString("Checking", R.string.Checking));
|
||||
colorKey = Theme.key_windowBackgroundWhiteGrayText2;
|
||||
} else {
|
||||
valueTextView.setText(LocaleController.getString("Connected", R.string.Connected));
|
||||
}
|
||||
|
@ -264,6 +261,28 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
|
|||
|
||||
updateRows(true);
|
||||
|
||||
UIUtil.runOnIoDispatcher(() -> {
|
||||
|
||||
int times = 0;
|
||||
|
||||
while (!ProxyUtil.reloadProxyList()) {
|
||||
|
||||
if (times > 5) return;
|
||||
|
||||
times++;
|
||||
|
||||
try {
|
||||
Thread.sleep(10 * 1000L);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SharedConfig.reloadProxyList();
|
||||
UIUtil.runOnUIThread(() -> updateRows(true));
|
||||
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -289,6 +308,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
|
|||
private int menu_export_json = 12;
|
||||
private int menu_import_json = 13;
|
||||
private int menu_delete_all = 14;
|
||||
private int menu_delete_unavailable = 15;
|
||||
|
||||
public void processProxyList(ArrayList<String> files) {
|
||||
|
||||
|
@ -351,7 +371,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
|
|||
|
||||
} catch (Exception ex) {
|
||||
|
||||
errors.put(proxyUrl, ex.getMessage());
|
||||
errors.put(proxyUrl.length() < 15 ? proxyUrl : (proxyUrl.substring(0, 15) + "..."), ex.getMessage());
|
||||
|
||||
}
|
||||
|
||||
|
@ -509,14 +529,23 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
|
|||
presentFragment(fragment);
|
||||
} else if (id == menu_delete_all) {
|
||||
AlertUtil.showConfirm(getParentActivity(),
|
||||
LocaleController.getString("DeleteAllProxies", R.string.DeleteAllProxies),
|
||||
LocaleController.getString("DeleteAllProxies", R.string.DeleteAllProxiesAlert),
|
||||
LocaleController.getString("DeleteAllServer", R.string.DeleteAllServer),
|
||||
LocaleController.getString("DeleteAllServerConfirm", R.string.DeleteAllServerConfirm),
|
||||
LocaleController.getString("Delete", R.string.Delete),
|
||||
true, (d, v) -> {
|
||||
SharedConfig.deleteAllProxy();
|
||||
updateRows(true);
|
||||
});
|
||||
}
|
||||
} else if (id == menu_delete_unavailable) {
|
||||
AlertUtil.showConfirm(getParentActivity(),
|
||||
LocaleController.getString("DeleteUnavailableServer", R.string.DeleteUnavailableServer),
|
||||
LocaleController.getString("DeleteUnavailableServerConfirm", R.string.DeleteUnavailableServerConfirm),
|
||||
LocaleController.getString("Delete", R.string.Delete),
|
||||
true, (d, v) -> {
|
||||
SharedConfig.deleteUnavailableProxy();
|
||||
updateRows(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -613,7 +642,8 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
|
|||
otherItem.addSubItem(menu_reorder_by_ping, LocaleController.getString("ReorderByPing", R.string.ReorderByPing));
|
||||
otherItem.addSubItem(menu_export_json, LocaleController.getString("ExportProxies", R.string.ExportProxies));
|
||||
otherItem.addSubItem(menu_import_json, LocaleController.getString("ImportProxies", R.string.ImportProxies));
|
||||
otherItem.addSubItem(menu_delete_all, LocaleController.getString("DeleteAllProxies", R.string.DeleteAllProxies));
|
||||
otherItem.addSubItem(menu_delete_all, LocaleController.getString("DeleteAllServer", R.string.DeleteAllServer));
|
||||
otherItem.addSubItem(menu_delete_unavailable, LocaleController.getString("DeleteUnavailableServer", R.string.DeleteUnavailableServer));
|
||||
|
||||
listAdapter = new ListAdapter(context);
|
||||
|
||||
|
@ -791,7 +821,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
|
|||
|
||||
if (alert != null) {
|
||||
|
||||
AlertUtil.showSimpleAlert(context,alert);
|
||||
AlertUtil.showSimpleAlert(context, alert);
|
||||
alert = null;
|
||||
|
||||
}
|
||||
|
@ -955,29 +985,49 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
|
|||
if (proxyInfo.checking || (SystemClock.elapsedRealtime() - proxyInfo.availableCheckTime < 2 * 60 * 1000L && !force)) {
|
||||
continue;
|
||||
}
|
||||
proxyInfo.checking = true;
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxyCheckDone, proxyInfo);
|
||||
checkSingleProxy(proxyInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (proxyInfo instanceof SharedConfig.ExternalSocks5Proxy && proxyInfo != SharedConfig.currentProxy) {
|
||||
((SharedConfig.ExternalSocks5Proxy) proxyInfo).start();
|
||||
}
|
||||
private void checkSingleProxy(SharedConfig.ProxyInfo proxyInfo) {
|
||||
|
||||
proxyInfo.proxyCheckPingId = ConnectionsManager.getInstance(currentAccount).checkProxy(proxyInfo.address, proxyInfo.port, proxyInfo.username, proxyInfo.password, proxyInfo.secret, time -> AndroidUtilities.runOnUIThread(() -> {
|
||||
proxyInfo.availableCheckTime = SystemClock.elapsedRealtime();
|
||||
proxyInfo.checking = false;
|
||||
if (time == -1) {
|
||||
checkSingleProxy(proxyInfo, proxyInfo instanceof SharedConfig.ExternalSocks5Proxy ? 3 : 0);
|
||||
|
||||
}
|
||||
|
||||
private void checkSingleProxy(SharedConfig.ProxyInfo proxyInfo, int repeat) {
|
||||
|
||||
proxyInfo.checking = true;
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxyCheckDone, proxyInfo);
|
||||
|
||||
if (proxyInfo instanceof SharedConfig.ExternalSocks5Proxy && !((SharedConfig.ExternalSocks5Proxy) proxyInfo).isStarted()) {
|
||||
((SharedConfig.ExternalSocks5Proxy) proxyInfo).start();
|
||||
}
|
||||
|
||||
proxyInfo.proxyCheckPingId = ConnectionsManager.getInstance(currentAccount).checkProxy(proxyInfo.address, proxyInfo.port, proxyInfo.username, proxyInfo.password, proxyInfo.secret, time -> AndroidUtilities.runOnUIThread(() -> {
|
||||
proxyInfo.availableCheckTime = SystemClock.elapsedRealtime();
|
||||
if (time == -1) {
|
||||
if (repeat > 0) {
|
||||
UIUtil.runOnIoDispatcher(() -> {
|
||||
checkSingleProxy(proxyInfo, repeat - 1);
|
||||
});
|
||||
} else {
|
||||
proxyInfo.checking = false;
|
||||
proxyInfo.available = false;
|
||||
proxyInfo.ping = 0;
|
||||
} else {
|
||||
proxyInfo.ping = time;
|
||||
proxyInfo.available = true;
|
||||
if (proxyInfo instanceof SharedConfig.ExternalSocks5Proxy && proxyInfo != SharedConfig.currentProxy) {
|
||||
((SharedConfig.ExternalSocks5Proxy) proxyInfo).stop();
|
||||
}
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxyCheckDone, proxyInfo);
|
||||
}
|
||||
} else {
|
||||
proxyInfo.checking = false;
|
||||
proxyInfo.ping = time;
|
||||
proxyInfo.available = true;
|
||||
if (proxyInfo instanceof SharedConfig.ExternalSocks5Proxy && proxyInfo != SharedConfig.currentProxy) {
|
||||
((SharedConfig.ExternalSocks5Proxy) proxyInfo).stop();
|
||||
}
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.proxyCheckDone, proxyInfo);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1019,6 +1069,8 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
|
|||
if (holder != null && holder.itemView instanceof TextDetailProxyCell) {
|
||||
TextDetailProxyCell cell = (TextDetailProxyCell) holder.itemView;
|
||||
cell.updateStatus();
|
||||
} else {
|
||||
updateRows(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package tw.nekomimi.nekogram
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.annotation.TargetApi
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
|
@ -12,6 +11,7 @@ import android.service.notification.NotificationListenerService
|
|||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationCompat
|
||||
import org.telegram.messenger.ApplicationLoader
|
||||
import org.telegram.messenger.KeepAliveJob
|
||||
import org.telegram.messenger.LocaleController
|
||||
import org.telegram.messenger.R
|
||||
import org.telegram.ui.LaunchActivity
|
||||
|
@ -23,6 +23,7 @@ class NekoXPushService : NotificationListenerService() {
|
|||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
ApplicationLoader.postInitApplication()
|
||||
KeepAliveJob.startJob()
|
||||
if (NekoConfig.residentNotification) {
|
||||
val activityIntent = Intent(this, LaunchActivity::class.java)
|
||||
val pendingIntent = PendingIntent.getActivity(this, 0, activityIntent, 0)
|
||||
|
|
|
@ -14,7 +14,7 @@ object ProxyManager {
|
|||
@JvmStatic
|
||||
fun getPortForBean(bean: AngConfig.VmessBean): Int {
|
||||
|
||||
val hash = (bean.address + bean.port + bean.path).hashCode().toString()
|
||||
val hash = (bean.address + bean.port + bean.id + bean.network + bean.path).hashCode().toString()
|
||||
|
||||
var port = pref.getInt(hash, -1)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package tw.nekomimi.nekogram
|
||||
|
||||
import com.v2ray.ang.V2RayConfig.SS_PROTOCOL
|
||||
import com.v2ray.ang.dto.AngConfig
|
||||
import com.v2ray.ang.util.Utils
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
|
@ -77,6 +78,9 @@ class ShadowsocksLoader {
|
|||
var method: String = "aes-256-cfb",
|
||||
var remarks: String? = null
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return super.equals(other) || (other is Bean && hash == other.hash)
|
||||
}
|
||||
|
||||
/*
|
||||
init {
|
||||
|
@ -126,7 +130,7 @@ class ShadowsocksLoader {
|
|||
|
||||
}
|
||||
|
||||
val methodAndPswd = Utils.decodeUrlSafe(link.username)
|
||||
val methodAndPswd = Utils.decode(link.username)
|
||||
|
||||
return Bean(
|
||||
link.host,
|
||||
|
|
|
@ -87,6 +87,10 @@ class ShadowsocksRLoader {
|
|||
|
||||
val hash = (host + remotePort + password + protocol + obfs + method).hashCode()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return super.equals(other) || (other is Bean && hash == other.hash)
|
||||
}
|
||||
|
||||
/*
|
||||
init {
|
||||
|
||||
|
@ -134,13 +138,13 @@ class ShadowsocksRLoader {
|
|||
|
||||
runCatching {
|
||||
|
||||
bean.obfs_param = Utils.decodeUrlSafe(httpUrl.queryParameter("obfsparam")!!)
|
||||
bean.obfs_param = Utils.decode(httpUrl.queryParameter("obfsparam")!!)
|
||||
|
||||
}
|
||||
|
||||
runCatching {
|
||||
|
||||
bean.protocol_param = Utils.decodeUrlSafe(httpUrl.queryParameter("protoparam")!!)
|
||||
bean.protocol_param = Utils.decode(httpUrl.queryParameter("protoparam")!!)
|
||||
|
||||
}
|
||||
|
||||
|
@ -150,7 +154,7 @@ class ShadowsocksRLoader {
|
|||
|
||||
if (remarks?.isNotBlank() == true) {
|
||||
|
||||
bean.remarks = Utils.decodeUrlSafe(remarks)
|
||||
bean.remarks = Utils.decode(remarks)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -35,8 +35,8 @@ import java.util.*
|
|||
|
||||
object ProxyUtil {
|
||||
|
||||
@JvmStatic
|
||||
val cacheFile = File(ApplicationLoader.applicationContext.filesDir.parent, "nekox/proxy_list.json")
|
||||
@JvmField
|
||||
val cacheFile = File(ApplicationLoader.applicationContext.filesDir.parentFile, "nekox/remote_proxy_list.json")
|
||||
|
||||
@JvmStatic
|
||||
fun isVPNEnabled(): Boolean {
|
||||
|
@ -214,7 +214,7 @@ object ProxyUtil {
|
|||
|
||||
FileLog.e(it)
|
||||
|
||||
AlertUtil.showToast(LocaleController.getString("BrokenLink", R.string.BrokenLink))
|
||||
AlertUtil.showToast("${LocaleController.getString("BrokenLink", R.string.BrokenLink)}: ${it.message}")
|
||||
|
||||
}
|
||||
|
||||
|
@ -257,9 +257,9 @@ object ProxyUtil {
|
|||
|
||||
}.getOrThrow()
|
||||
|
||||
if (SharedConfig.addProxy(info) != info) {
|
||||
if (!(SharedConfig.addProxy(info) === info)) {
|
||||
|
||||
error("proxy already exists")
|
||||
error("already exists")
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,12 @@ import kotlinx.coroutines.GlobalScope
|
|||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.Dispatcher
|
||||
import org.telegram.messenger.ApplicationLoader
|
||||
|
||||
object UIUtil {
|
||||
|
||||
val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
@JvmStatic
|
||||
fun runOnUIThread(runnable: Runnable) = handler.post(runnable)
|
||||
fun runOnUIThread(runnable: Runnable) = ApplicationLoader.applicationHandler.post(runnable)
|
||||
|
||||
@JvmStatic
|
||||
fun runOnIoDispatcher(runnable: Runnable) {
|
||||
|
|
|
@ -102,15 +102,17 @@
|
|||
<string name="ReorderByPing">Reorder servers by ping</string>
|
||||
<string name="ExportProxies">Export servers to file</string>
|
||||
<string name="ImportProxies">Import servers from file</string>
|
||||
<string name="ImportProxyList">Import proxy servers</string>
|
||||
<string name="ImportProxyList">Import proxy servers</string>
|
||||
<string name="ImportProxyListConfirm">Are you sure you want to **import proxy servers**?</string>
|
||||
|
||||
<string name="InvalidProxyFile">Invalid proxy list file: </string>
|
||||
<string name="ImportedProxies">Imported proxy servers: </string>
|
||||
<string name="ErrorsInImport">Import errors: </string>
|
||||
<string name="NoProxy">You haven\'t added any proxy servers.</string>
|
||||
<string name="DeleteAllProxies">Delete all servers</string>
|
||||
<string name="DeleteAllProxiesAlert">Warning! This will **delete all proxies**.</string>
|
||||
<string name="DeleteAllServer">Delete all servers</string>
|
||||
<string name="DeleteUnavailableServer">Delete unavailable servers</string>
|
||||
<string name="DeleteAllServerConfirm">Are you sure you want to **delete all servers**?</string>
|
||||
<string name="DeleteUnavailableServerConfirm">Are you sure you want to **delete unavailable servers**?</string>
|
||||
|
||||
<string name="MinApi21Required">Sorry, you need at least Android 5 (API21).</string>
|
||||
|
||||
|
|
Loading…
Reference in New Issue