Support multiple named built-in proxies (5 LTE + 2 WiFi)

- XrayServers now holds a structured server list with per-entry name and local port
- XrayController builds built-in proxies from the list (createBuiltinProxies/byPort)
- ProxyInfo gains builtinName; proxy list shows the configured name
- Built-in proxies keep the same protection: read-only, not editable/shareable
- Credentials stay in git-ignored XrayServers.java; template updated

Verified: TMessagesProj compileReleaseJavaWithJavac succeeds.
This commit is contained in:
instant992 2026-06-09 03:42:14 +04:00
parent d79c149e3e
commit d200a290f8
5 changed files with 86 additions and 65 deletions

View file

@ -411,11 +411,8 @@ public class ApplicationLoader extends Application {
SharedConfig.loadProxyList(); SharedConfig.loadProxyList();
SharedConfig.ProxyInfo proxy = SharedConfig.currentProxy; SharedConfig.ProxyInfo proxy = SharedConfig.currentProxy;
if (proxy == null || !proxy.isVless()) { if (proxy == null || !proxy.isVless()) {
if (savedPort == 10809) { proxy = XrayController.createBuiltinProxyByPort(savedPort);
proxy = XrayController.createBuiltinProxy2(); if (proxy == null) {
} else if (savedPort == 10810) {
proxy = XrayController.createBuiltinProxy3();
} else {
proxy = XrayController.createBuiltinProxy(); proxy = XrayController.createBuiltinProxy();
} }
} }

View file

@ -399,6 +399,8 @@ public class SharedConfig {
/** True for the built-in hidden proxy — cannot be edited or deleted. */ /** True for the built-in hidden proxy — cannot be edited or deleted. */
public boolean builtin = false; public boolean builtin = false;
/** Display name for a built-in proxy (e.g. "LTE 1", "WiFi 2"). */
public String builtinName = "";
public int vlessLocalPort = 10808; public int vlessLocalPort = 10808;
public long proxyCheckPingId; public long proxyCheckPingId;
@ -1590,12 +1592,11 @@ public class SharedConfig {
if (p.builtin) { hasBuiltin = true; break; } if (p.builtin) { hasBuiltin = true; break; }
} }
if (!hasBuiltin) { if (!hasBuiltin) {
ProxyInfo b3 = XrayController.createBuiltinProxy3(); List<ProxyInfo> builtins = XrayController.createBuiltinProxies();
ProxyInfo b2 = XrayController.createBuiltinProxy2(); // Insert at top preserving declaration order.
ProxyInfo b1 = XrayController.createBuiltinProxy(); for (int i = builtins.size() - 1; i >= 0; i--) {
if (b3 != null) proxyList.add(0, b3); proxyList.add(0, builtins.get(i));
if (b2 != null) proxyList.add(0, b2); }
if (b1 != null) proxyList.add(0, b1);
} }
} }

View file

@ -30,30 +30,43 @@ public class XrayController {
// --- Built-in proxies (hidden, read-only) --- // --- Built-in proxies (hidden, read-only) ---
// Server credentials live in XrayServers.java (git-ignored). // Server credentials live in XrayServers.java (git-ignored).
/** Build all configured built-in proxies, in declaration order. */
public static java.util.List<SharedConfig.ProxyInfo> createBuiltinProxies() {
java.util.List<SharedConfig.ProxyInfo> list = new java.util.ArrayList<>();
for (XrayServers.Server s : XrayServers.SERVERS) {
SharedConfig.ProxyInfo p = fromServer(s);
if (p != null) list.add(p);
}
return list;
}
/** Build the built-in proxy assigned to the given local SOCKS5 port. */
public static SharedConfig.ProxyInfo createBuiltinProxyByPort(int localPort) {
for (XrayServers.Server s : XrayServers.SERVERS) {
if (s.localPort == localPort) {
return fromServer(s);
}
}
return null;
}
/** Build the first configured built-in proxy, or null if none. */
public static SharedConfig.ProxyInfo createBuiltinProxy() { public static SharedConfig.ProxyInfo createBuiltinProxy() {
if (XrayServers.B1_ADDR == null || XrayServers.B1_ADDR.isEmpty()) return null; for (XrayServers.Server s : XrayServers.SERVERS) {
SharedConfig.ProxyInfo p = SharedConfig.ProxyInfo.createVless( SharedConfig.ProxyInfo p = fromServer(s);
XrayServers.B1_ADDR, XrayServers.B1_PORT, XrayServers.B1_UUID, XrayServers.B1_PBK, if (p != null) return p;
XrayServers.B1_SID, XrayServers.B1_FP, XrayServers.B1_SNI, 10808, "tcp", ""); }
p.builtin = true; return null;
return p;
} }
public static SharedConfig.ProxyInfo createBuiltinProxy2() { private static SharedConfig.ProxyInfo fromServer(XrayServers.Server s) {
if (XrayServers.B2_ADDR == null || XrayServers.B2_ADDR.isEmpty()) return null; if (s == null || s.address == null || s.address.isEmpty()) return null;
SharedConfig.ProxyInfo p = SharedConfig.ProxyInfo.createVless( SharedConfig.ProxyInfo p = SharedConfig.ProxyInfo.createVless(
XrayServers.B2_ADDR, XrayServers.B2_PORT, XrayServers.B2_UUID, XrayServers.B2_PBK, s.address, s.port, s.uuid, s.publicKey,
XrayServers.B2_SID, XrayServers.B2_FP, XrayServers.B2_SNI, 10809, "grpc", "name"); s.shortId, s.fingerprint, s.sni, s.localPort,
p.builtin = true; s.network, s.serviceName);
return p;
}
public static SharedConfig.ProxyInfo createBuiltinProxy3() {
if (XrayServers.B3_ADDR == null || XrayServers.B3_ADDR.isEmpty()) return null;
SharedConfig.ProxyInfo p = SharedConfig.ProxyInfo.createVless(
XrayServers.B3_ADDR, XrayServers.B3_PORT, XrayServers.B3_UUID, XrayServers.B3_PBK,
XrayServers.B3_SID, XrayServers.B3_FP, XrayServers.B3_SNI, 10810, "tcp", "");
p.builtin = true; p.builtin = true;
p.builtinName = s.name != null ? s.name : "";
return p; return p;
} }

View file

@ -7,37 +7,54 @@ package org.telegram.messenger;
* extension) and fill in your own VLESS+Reality server data. The real * extension) and fill in your own VLESS+Reality server data. The real
* XrayServers.java is git-ignored so server credentials never reach the repo. * XrayServers.java is git-ignored so server credentials never reach the repo.
* *
* Leaving the addresses empty disables the bundled proxies — the app still * Leaving the SERVERS array empty disables the bundled proxies — the app still
* works, you just won't see the pre-configured entries in the proxy list. * works, you just won't see the pre-configured entries in the proxy list.
*
* Each entry is parsed from a vless:// link. The data is read-only at runtime:
* built-in proxies cannot be edited, shared, exported or inspected from the UI.
*/ */
final class XrayServers { final class XrayServers {
private XrayServers() {} private XrayServers() {}
// Proxy 1 — port 10808 /** A single built-in VLESS+Reality server. */
static final String B1_ADDR = ""; static final class Server {
static final int B1_PORT = 443; final String name;
static final String B1_UUID = ""; final String address;
static final String B1_PBK = ""; final int port;
static final String B1_SID = ""; final String uuid;
static final String B1_FP = "chrome"; final String publicKey;
static final String B1_SNI = ""; final String shortId;
final String fingerprint;
final String sni;
final String network; // "tcp" or "grpc"
final String serviceName; // gRPC serviceName, empty for tcp
final int localPort; // local SOCKS5 port assigned to this entry
// Proxy 2 — gRPC, port 10809 Server(String name, String address, int port, String uuid, String publicKey,
static final String B2_ADDR = ""; String shortId, String fingerprint, String sni,
static final int B2_PORT = 443; String network, String serviceName, int localPort) {
static final String B2_UUID = ""; this.name = name;
static final String B2_PBK = ""; this.address = address;
static final String B2_SID = ""; this.port = port;
static final String B2_FP = "chrome"; this.uuid = uuid;
static final String B2_SNI = ""; this.publicKey = publicKey;
this.shortId = shortId;
// Proxy 3 — TCP/Vision, port 10810 this.fingerprint = fingerprint;
static final String B3_ADDR = ""; this.sni = sni;
static final int B3_PORT = 443; this.network = network;
static final String B3_UUID = ""; this.serviceName = serviceName;
static final String B3_PBK = ""; this.localPort = localPort;
static final String B3_SID = ""; }
static final String B3_FP = "chrome"; }
static final String B3_SNI = "";
// Built-in servers. Order defines display order in the proxy list.
// localPort must be unique per entry (used as a stable identifier).
//
// Example entry parsed from:
// vless://UUID@host:port?security=reality&pbk=PBK&sid=SID&fp=chrome&sni=SNI&flow=xtls-rprx-vision#Name
//
// new Server("Name", "host", port, "UUID", "PBK", "SID", "chrome", "SNI", "tcp", "", 10808),
static final Server[] SERVERS = new Server[] {
};
} }

View file

@ -194,16 +194,9 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente
public void setProxy(SharedConfig.ProxyInfo proxyInfo) { public void setProxy(SharedConfig.ProxyInfo proxyInfo) {
if (proxyInfo.builtin) { if (proxyInfo.builtin) {
// Name by local port used as identifier String name = proxyInfo.builtinName != null && !proxyInfo.builtinName.isEmpty()
int lp = proxyInfo.vlessLocalPort; ? proxyInfo.builtinName
String name; : "Proxy";
if (lp == 10809) {
name = "Proxy WiFi - 1";
} else if (lp == 10810) {
name = "Proxy WiFi - 2";
} else {
name = "LTE — обход | Все операторы";
}
textView.setText(name); textView.setText(name);
checkImageView.setVisibility(GONE); checkImageView.setVisibility(GONE);
checkImageView.setClickable(false); checkImageView.setClickable(false);