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.ProxyInfo proxy = SharedConfig.currentProxy;
if (proxy == null || !proxy.isVless()) {
if (savedPort == 10809) {
proxy = XrayController.createBuiltinProxy2();
} else if (savedPort == 10810) {
proxy = XrayController.createBuiltinProxy3();
} else {
proxy = XrayController.createBuiltinProxyByPort(savedPort);
if (proxy == null) {
proxy = XrayController.createBuiltinProxy();
}
}

View file

@ -399,6 +399,8 @@ public class SharedConfig {
/** True for the built-in hidden proxy — cannot be edited or deleted. */
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 long proxyCheckPingId;
@ -1590,12 +1592,11 @@ public class SharedConfig {
if (p.builtin) { hasBuiltin = true; break; }
}
if (!hasBuiltin) {
ProxyInfo b3 = XrayController.createBuiltinProxy3();
ProxyInfo b2 = XrayController.createBuiltinProxy2();
ProxyInfo b1 = XrayController.createBuiltinProxy();
if (b3 != null) proxyList.add(0, b3);
if (b2 != null) proxyList.add(0, b2);
if (b1 != null) proxyList.add(0, b1);
List<ProxyInfo> builtins = XrayController.createBuiltinProxies();
// Insert at top preserving declaration order.
for (int i = builtins.size() - 1; i >= 0; i--) {
proxyList.add(0, builtins.get(i));
}
}
}

View file

@ -30,30 +30,43 @@ public class XrayController {
// --- Built-in proxies (hidden, read-only) ---
// 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() {
if (XrayServers.B1_ADDR == null || XrayServers.B1_ADDR.isEmpty()) return null;
SharedConfig.ProxyInfo p = SharedConfig.ProxyInfo.createVless(
XrayServers.B1_ADDR, XrayServers.B1_PORT, XrayServers.B1_UUID, XrayServers.B1_PBK,
XrayServers.B1_SID, XrayServers.B1_FP, XrayServers.B1_SNI, 10808, "tcp", "");
p.builtin = true;
return p;
for (XrayServers.Server s : XrayServers.SERVERS) {
SharedConfig.ProxyInfo p = fromServer(s);
if (p != null) return p;
}
return null;
}
public static SharedConfig.ProxyInfo createBuiltinProxy2() {
if (XrayServers.B2_ADDR == null || XrayServers.B2_ADDR.isEmpty()) return null;
private static SharedConfig.ProxyInfo fromServer(XrayServers.Server s) {
if (s == null || s.address == null || s.address.isEmpty()) return null;
SharedConfig.ProxyInfo p = SharedConfig.ProxyInfo.createVless(
XrayServers.B2_ADDR, XrayServers.B2_PORT, XrayServers.B2_UUID, XrayServers.B2_PBK,
XrayServers.B2_SID, XrayServers.B2_FP, XrayServers.B2_SNI, 10809, "grpc", "name");
p.builtin = true;
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", "");
s.address, s.port, s.uuid, s.publicKey,
s.shortId, s.fingerprint, s.sni, s.localPort,
s.network, s.serviceName);
p.builtin = true;
p.builtinName = s.name != null ? s.name : "";
return p;
}

View file

@ -7,37 +7,54 @@ package org.telegram.messenger;
* extension) and fill in your own VLESS+Reality server data. The real
* 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.
*
* 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 {
private XrayServers() {}
// Proxy 1 — port 10808
static final String B1_ADDR = "";
static final int B1_PORT = 443;
static final String B1_UUID = "";
static final String B1_PBK = "";
static final String B1_SID = "";
static final String B1_FP = "chrome";
static final String B1_SNI = "";
/** A single built-in VLESS+Reality server. */
static final class Server {
final String name;
final String address;
final int port;
final String uuid;
final String publicKey;
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
static final String B2_ADDR = "";
static final int B2_PORT = 443;
static final String B2_UUID = "";
static final String B2_PBK = "";
static final String B2_SID = "";
static final String B2_FP = "chrome";
static final String B2_SNI = "";
Server(String name, String address, int port, String uuid, String publicKey,
String shortId, String fingerprint, String sni,
String network, String serviceName, int localPort) {
this.name = name;
this.address = address;
this.port = port;
this.uuid = uuid;
this.publicKey = publicKey;
this.shortId = shortId;
this.fingerprint = fingerprint;
this.sni = sni;
this.network = network;
this.serviceName = serviceName;
this.localPort = localPort;
}
}
// Proxy 3 — TCP/Vision, port 10810
static final String B3_ADDR = "";
static final int B3_PORT = 443;
static final String B3_UUID = "";
static final String B3_PBK = "";
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) {
if (proxyInfo.builtin) {
// Name by local port used as identifier
int lp = proxyInfo.vlessLocalPort;
String name;
if (lp == 10809) {
name = "Proxy WiFi - 1";
} else if (lp == 10810) {
name = "Proxy WiFi - 2";
} else {
name = "LTE — обход | Все операторы";
}
String name = proxyInfo.builtinName != null && !proxyInfo.builtinName.isEmpty()
? proxyInfo.builtinName
: "Proxy";
textView.setText(name);
checkImageView.setVisibility(GONE);
checkImageView.setClickable(false);