Merge branch '2dust:master' into master

This commit is contained in:
fonaix 2024-12-01 14:50:18 +08:00 committed by GitHub
commit d8b0363bb7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 128 additions and 212 deletions

31
.github/workflows/winget-publish.yml vendored Normal file
View file

@ -0,0 +1,31 @@
name: WinGet submission on release
# based off of https://github.com/nushell/nushell/blob/main/.github/workflows/winget-submission.yml
# inspired by https://github.com/microsoft/PowerToys/blob/main/.github/workflows/package-submissions.yml
# Modified by @MerrickZ https://github.com/anpho
on:
workflow_dispatch:
release:
types: [released]
jobs:
winget:
name: Publish winget package
runs-on: windows-latest
steps:
- name: Submit v2ray package to Windows Package Manager Community Repository
run: |
$wingetPackage = "2dust.v2rayN"
$gitToken = "${{ secrets.PT_WINGET }}"
$github = Invoke-RestMethod -uri "https://api.github.com/repos/2dust/v2rayN/releases"
$targetRelease = $github | Where-Object -Property prerelease -match 'False' | Select -First 1
$installerUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'v2rayN-windows-64-With-Core\.zip*' | Select -ExpandProperty browser_download_url
$ver = $targetRelease.tag_name
# getting latest wingetcreate file
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
.\wingetcreate.exe update $wingetPackage -s -v $ver -u "$installerUrl|x64" -t $gitToken

View file

@ -31,8 +31,8 @@
var parts = this.version.Split('.'); var parts = this.version.Split('.');
if (parts.Length == 2) if (parts.Length == 2)
{ {
this.major = int.Parse(parts[0]); this.major = int.Parse(parts.First());
this.minor = int.Parse(parts[1]); this.minor = int.Parse(parts.Last());
this.patch = 0; this.patch = 0;
} }
else if (parts.Length is 3 or 4) else if (parts.Length is 3 or 4)

View file

@ -22,7 +22,7 @@ namespace ServiceLib.Common
public static bool BeginWithAny(this string s, IEnumerable<char> chars) public static bool BeginWithAny(this string s, IEnumerable<char> chars)
{ {
if (s.IsNullOrEmpty()) return false; if (s.IsNullOrEmpty()) return false;
return chars.Contains(s[0]); return chars.Contains(s.First());
} }
private static bool IsWhiteSpace(this string value) private static bool IsWhiteSpace(this string value)
@ -61,7 +61,7 @@ namespace ServiceLib.Common
return string.Empty; return string.Empty;
} }
return char.ToUpper(value[0]) + value[1..]; return char.ToUpper(value.First()) + value[1..];
} }
public static string AppendQuotes(this string value) public static string AppendQuotes(this string value)

View file

@ -313,8 +313,8 @@ namespace ServiceLib.Common
continue; continue;
} }
var key = Uri.UnescapeDataString(keyValue[0]); var key = Uri.UnescapeDataString(keyValue.First());
var val = Uri.UnescapeDataString(keyValue[1]); var val = Uri.UnescapeDataString(keyValue.Last());
if (result[key] is null) if (result[key] is null)
{ {
@ -622,8 +622,8 @@ namespace ServiceLib.Common
{ {
if (host.StartsWith("#")) continue; if (host.StartsWith("#")) continue;
var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
if (hostItem.Length < 2) continue; if (hostItem.Length != 2) continue;
systemHosts.Add(hostItem[1], hostItem[0]); systemHosts.Add(hostItem.Last(), hostItem.First());
} }
} }
} }

View file

@ -62,7 +62,7 @@ namespace ServiceLib.Handler
{ {
if (config.Inbound.Count > 0) if (config.Inbound.Count > 0)
{ {
config.Inbound[0].Protocol = EInboundProtocol.socks.ToString(); config.Inbound.First().Protocol = EInboundProtocol.socks.ToString();
} }
} }
@ -70,7 +70,7 @@ namespace ServiceLib.Handler
if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy)) if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy))
{ {
config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies[0];//"IPIfNonMatch"; config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies.First();//"IPIfNonMatch";
} }
config.KcpItem ??= new KcpItem config.KcpItem ??= new KcpItem
@ -111,7 +111,7 @@ namespace ServiceLib.Handler
{ {
if (Thread.CurrentThread.CurrentCulture.Name.Equals("zh-cn", StringComparison.CurrentCultureIgnoreCase)) if (Thread.CurrentThread.CurrentCulture.Name.Equals("zh-cn", StringComparison.CurrentCultureIgnoreCase))
{ {
config.UiItem.CurrentLanguage = Global.Languages[0]; config.UiItem.CurrentLanguage = Global.Languages.First();
} }
else else
{ {
@ -132,7 +132,7 @@ namespace ServiceLib.Handler
} }
if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedTestUrl)) if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedTestUrl))
{ {
config.SpeedTestItem.SpeedTestUrl = Global.SpeedTestUrls[0]; config.SpeedTestItem.SpeedTestUrl = Global.SpeedTestUrls.First();
} }
if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedPingTestUrl)) if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedPingTestUrl))
{ {
@ -148,7 +148,7 @@ namespace ServiceLib.Handler
config.Mux4SboxItem ??= new() config.Mux4SboxItem ??= new()
{ {
Protocol = Global.SingboxMuxs[0], Protocol = Global.SingboxMuxs.First(),
MaxConnections = 8 MaxConnections = 8
}; };
@ -429,7 +429,7 @@ namespace ServiceLib.Handler
{ {
return 0; return 0;
} }
sort = ProfileExHandler.Instance.GetSort(lstProfile[0].IndexId) - 1; sort = ProfileExHandler.Instance.GetSort(lstProfile.First().IndexId) - 1;
break; break;
} }

View file

@ -99,8 +99,8 @@ namespace ServiceLib.Handler.Fmt
{ {
return null; return null;
} }
item.Security = userInfoParts[0]; item.Security = userInfoParts.First();
item.Id = Utils.UrlDecode(userInfoParts[1]); item.Id = Utils.UrlDecode(userInfoParts.Last());
} }
else else
{ {
@ -111,8 +111,8 @@ namespace ServiceLib.Handler.Fmt
{ {
return null; return null;
} }
item.Security = userInfoParts[0]; item.Security = userInfoParts.First();
item.Id = userInfoParts[1]; item.Id = userInfoParts.Last();
} }
var queryParameters = Utils.ParseQueryString(parsedUrl.Query); var queryParameters = Utils.ParseQueryString(parsedUrl.Query);

View file

@ -5,9 +5,8 @@
public static ProfileItem? Resolve(string str, out string msg) public static ProfileItem? Resolve(string str, out string msg)
{ {
msg = ResUI.ConfigurationFormatIncorrect; msg = ResUI.ConfigurationFormatIncorrect;
ProfileItem? item;
item = ResolveSocksNew(str) ?? ResolveSocks(str); var item = ResolveSocksNew(str) ?? ResolveSocks(str);
if (item == null) if (item == null)
{ {
return null; return null;
@ -25,19 +24,13 @@
public static string? ToUri(ProfileItem? item) public static string? ToUri(ProfileItem? item)
{ {
if (item == null) return null; if (item == null) return null;
string url = string.Empty; var url = string.Empty;
string remark = string.Empty; var remark = string.Empty;
if (Utils.IsNotEmpty(item.Remarks)) if (Utils.IsNotEmpty(item.Remarks))
{ {
remark = "#" + Utils.UrlEncode(item.Remarks); remark = "#" + Utils.UrlEncode(item.Remarks);
} }
//url = string.Format("{0}:{1}@{2}:{3}",
// item.security,
// item.id,
// item.address,
// item.port);
//url = Utile.Base64Encode(url);
//new //new
var pw = Utils.Base64Encode($"{item.Security}:{item.Id}"); var pw = Utils.Base64Encode($"{item.Security}:{item.Id}");
return ToUri(EConfigType.SOCKS, item.Address, item.Port, pw, null, remark); return ToUri(EConfigType.SOCKS, item.Address, item.Port, pw, null, remark);
@ -51,7 +44,7 @@
}; };
result = result[Global.ProtocolShares[EConfigType.SOCKS].Length..]; result = result[Global.ProtocolShares[EConfigType.SOCKS].Length..];
//remark //remark
int indexRemark = result.IndexOf("#"); var indexRemark = result.IndexOf("#");
if (indexRemark > 0) if (indexRemark > 0)
{ {
try try
@ -62,7 +55,7 @@
result = result[..indexRemark]; result = result[..indexRemark];
} }
//part decode //part decode
int indexS = result.IndexOf("@"); var indexS = result.IndexOf("@");
if (indexS > 0) if (indexS > 0)
{ {
} }
@ -71,21 +64,20 @@
result = Utils.Base64Decode(result); result = Utils.Base64Decode(result);
} }
string[] arr1 = result.Split('@'); var arr1 = result.Split('@');
if (arr1.Length != 2) if (arr1.Length != 2)
{ {
return null; return null;
} }
string[] arr21 = arr1[0].Split(':'); var arr21 = arr1.First().Split(':');
//string[] arr22 = arr1[1].Split(':'); var indexPort = arr1.Last().LastIndexOf(":");
int indexPort = arr1[1].LastIndexOf(":");
if (arr21.Length != 2 || indexPort < 0) if (arr21.Length != 2 || indexPort < 0)
{ {
return null; return null;
} }
item.Address = arr1[1][..indexPort]; item.Address = arr1[1][..indexPort];
item.Port = Utils.ToInt(arr1[1][(indexPort + 1)..]); item.Port = Utils.ToInt(arr1[1][(indexPort + 1)..]);
item.Security = arr21[0]; item.Security = arr21.First();
item.Id = arr21[1]; item.Id = arr21[1];
return item; return item;
@ -106,10 +98,10 @@
// parse base64 UserInfo // parse base64 UserInfo
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo); var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
var userInfo = Utils.Base64Decode(rawUserInfo); var userInfo = Utils.Base64Decode(rawUserInfo);
var userInfoParts = userInfo.Split(new[] { ':' }, 2); var userInfoParts = userInfo.Split([':'], 2);
if (userInfoParts.Length == 2) if (userInfoParts.Length == 2)
{ {
item.Security = userInfoParts[0]; item.Security = userInfoParts.First();
item.Id = userInfoParts[1]; item.Id = userInfoParts[1];
} }

View file

@ -21,8 +21,8 @@
var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2); var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
if (userInfoParts.Length == 2) if (userInfoParts.Length == 2)
{ {
item.Id = userInfoParts[0]; item.Id = userInfoParts.First();
item.Security = userInfoParts[1]; item.Security = userInfoParts.Last();
} }
var query = Utils.ParseQueryString(url.Query); var query = Utils.ParseQueryString(url.Query);

View file

@ -222,7 +222,6 @@
public int ProxiesSorting { get; set; } public int ProxiesSorting { get; set; }
public bool ProxiesAutoRefresh { get; set; } public bool ProxiesAutoRefresh { get; set; }
public int ProxiesAutoDelayTestInterval { get; set; } = 10; public int ProxiesAutoDelayTestInterval { get; set; } = 10;
public int ConnectionsSorting { get; set; }
public bool ConnectionsAutoRefresh { get; set; } public bool ConnectionsAutoRefresh { get; set; }
public int ConnectionsRefreshInterval { get; set; } = 2; public int ConnectionsRefreshInterval { get; set; } = 2;
} }

View file

@ -88,7 +88,7 @@ namespace ServiceLib.Services.CoreConfig
//external-controller //external-controller
fileContent["external-controller"] = $"{Global.Loopback}:{AppHandler.Instance.StatePort2}"; fileContent["external-controller"] = $"{Global.Loopback}:{AppHandler.Instance.StatePort2}";
//allow-lan //allow-lan
if (_config.Inbound[0].AllowLANConn) if (_config.Inbound.First().AllowLANConn)
{ {
fileContent["allow-lan"] = "true"; fileContent["allow-lan"] = "true";
fileContent["bind-address"] = "*"; fileContent["bind-address"] = "*";

View file

@ -52,7 +52,7 @@ namespace ServiceLib.Services.CoreConfig
await GenInbounds(singboxConfig); await GenInbounds(singboxConfig);
await GenOutbound(node, singboxConfig.outbounds[0]); await GenOutbound(node, singboxConfig.outbounds.First());
await GenMoreOutbounds(node, singboxConfig); await GenMoreOutbounds(node, singboxConfig);
@ -495,8 +495,8 @@ namespace ServiceLib.Services.CoreConfig
singboxConfig.inbounds.Add(inbound); singboxConfig.inbounds.Add(inbound);
inbound.listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks); inbound.listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
inbound.sniff = _config.Inbound[0].SniffingEnabled; inbound.sniff = _config.Inbound.First().SniffingEnabled;
inbound.sniff_override_destination = _config.Inbound[0].RouteOnly ? false : _config.Inbound[0].SniffingEnabled; inbound.sniff_override_destination = _config.Inbound.First().RouteOnly ? false : _config.Inbound.First().SniffingEnabled;
inbound.domain_strategy = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainStrategy4Singbox) ? null : _config.RoutingBasicItem.DomainStrategy4Singbox; inbound.domain_strategy = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainStrategy4Singbox) ? null : _config.RoutingBasicItem.DomainStrategy4Singbox;
var routing = await ConfigHandler.GetDefaultRouting(_config); var routing = await ConfigHandler.GetDefaultRouting(_config);
@ -509,9 +509,9 @@ namespace ServiceLib.Services.CoreConfig
var inbound2 = GetInbound(inbound, EInboundProtocol.http, false); var inbound2 = GetInbound(inbound, EInboundProtocol.http, false);
singboxConfig.inbounds.Add(inbound2); singboxConfig.inbounds.Add(inbound2);
if (_config.Inbound[0].AllowLANConn) if (_config.Inbound.First().AllowLANConn)
{ {
if (_config.Inbound[0].NewPort4LAN) if (_config.Inbound.First().NewPort4LAN)
{ {
var inbound3 = GetInbound(inbound, EInboundProtocol.socks2, true); var inbound3 = GetInbound(inbound, EInboundProtocol.socks2, true);
inbound3.listen = listen; inbound3.listen = listen;
@ -522,10 +522,10 @@ namespace ServiceLib.Services.CoreConfig
singboxConfig.inbounds.Add(inbound4); singboxConfig.inbounds.Add(inbound4);
//auth //auth
if (Utils.IsNotEmpty(_config.Inbound[0].User) && Utils.IsNotEmpty(_config.Inbound[0].Pass)) if (Utils.IsNotEmpty(_config.Inbound.First().User) && Utils.IsNotEmpty(_config.Inbound.First().Pass))
{ {
inbound3.users = new() { new() { username = _config.Inbound[0].User, password = _config.Inbound[0].Pass } }; inbound3.users = new() { new() { username = _config.Inbound.First().User, password = _config.Inbound.First().Pass } };
inbound4.users = new() { new() { username = _config.Inbound[0].User, password = _config.Inbound[0].Pass } }; inbound4.users = new() { new() { username = _config.Inbound.First().User, password = _config.Inbound.First().Pass } };
} }
} }
else else
@ -540,11 +540,11 @@ namespace ServiceLib.Services.CoreConfig
{ {
if (_config.TunModeItem.Mtu <= 0) if (_config.TunModeItem.Mtu <= 0)
{ {
_config.TunModeItem.Mtu = Utils.ToInt(Global.TunMtus[0]); _config.TunModeItem.Mtu = Utils.ToInt(Global.TunMtus.First());
} }
if (Utils.IsNullOrEmpty(_config.TunModeItem.Stack)) if (Utils.IsNullOrEmpty(_config.TunModeItem.Stack))
{ {
_config.TunModeItem.Stack = Global.TunStacks[0]; _config.TunModeItem.Stack = Global.TunStacks.First();
} }
var tunInbound = JsonUtils.Deserialize<Inbound4Sbox>(Utils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { }; var tunInbound = JsonUtils.Deserialize<Inbound4Sbox>(Utils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { };
@ -552,8 +552,8 @@ namespace ServiceLib.Services.CoreConfig
tunInbound.mtu = _config.TunModeItem.Mtu; tunInbound.mtu = _config.TunModeItem.Mtu;
tunInbound.strict_route = _config.TunModeItem.StrictRoute; tunInbound.strict_route = _config.TunModeItem.StrictRoute;
tunInbound.stack = _config.TunModeItem.Stack; tunInbound.stack = _config.TunModeItem.Stack;
tunInbound.sniff = _config.Inbound[0].SniffingEnabled; tunInbound.sniff = _config.Inbound.First().SniffingEnabled;
//tunInbound.sniff_override_destination = _config.inbound[0].routeOnly ? false : _config.inbound[0].sniffingEnabled; //tunInbound.sniff_override_destination = _config.inbound.First().routeOnly ? false : _config.inbound.First().sniffingEnabled;
if (_config.TunModeItem.EnableIPv6Address == false) if (_config.TunModeItem.EnableIPv6Address == false)
{ {
tunInbound.address = ["172.18.0.1/30"]; tunInbound.address = ["172.18.0.1/30"];
@ -867,7 +867,7 @@ namespace ServiceLib.Services.CoreConfig
} }
//current proxy //current proxy
var outbound = singboxConfig.outbounds[0]; var outbound = singboxConfig.outbounds.First();
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound); var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
//Previous proxy //Previous proxy
@ -910,7 +910,7 @@ namespace ServiceLib.Services.CoreConfig
try try
{ {
var dnsOutbound = "dns_out"; var dnsOutbound = "dns_out";
if (!_config.Inbound[0].SniffingEnabled) if (!_config.Inbound.First().SniffingEnabled)
{ {
singboxConfig.route.rules.Add(new() singboxConfig.route.rules.Add(new()
{ {

View file

@ -55,7 +55,7 @@ namespace ServiceLib.Services.CoreConfig
await GenRouting(v2rayConfig); await GenRouting(v2rayConfig);
await GenOutbound(node, v2rayConfig.outbounds[0]); await GenOutbound(node, v2rayConfig.outbounds.First());
await GenMoreOutbounds(node, v2rayConfig); await GenMoreOutbounds(node, v2rayConfig);
@ -391,33 +391,33 @@ namespace ServiceLib.Services.CoreConfig
var listen = "0.0.0.0"; var listen = "0.0.0.0";
v2rayConfig.inbounds = []; v2rayConfig.inbounds = [];
Inbounds4Ray? inbound = GetInbound(_config.Inbound[0], EInboundProtocol.socks, true); Inbounds4Ray? inbound = GetInbound(_config.Inbound.First(), EInboundProtocol.socks, true);
v2rayConfig.inbounds.Add(inbound); v2rayConfig.inbounds.Add(inbound);
//http //http
Inbounds4Ray? inbound2 = GetInbound(_config.Inbound[0], EInboundProtocol.http, false); Inbounds4Ray? inbound2 = GetInbound(_config.Inbound.First(), EInboundProtocol.http, false);
v2rayConfig.inbounds.Add(inbound2); v2rayConfig.inbounds.Add(inbound2);
if (_config.Inbound[0].AllowLANConn) if (_config.Inbound.First().AllowLANConn)
{ {
if (_config.Inbound[0].NewPort4LAN) if (_config.Inbound.First().NewPort4LAN)
{ {
var inbound3 = GetInbound(_config.Inbound[0], EInboundProtocol.socks2, true); var inbound3 = GetInbound(_config.Inbound.First(), EInboundProtocol.socks2, true);
inbound3.listen = listen; inbound3.listen = listen;
v2rayConfig.inbounds.Add(inbound3); v2rayConfig.inbounds.Add(inbound3);
var inbound4 = GetInbound(_config.Inbound[0], EInboundProtocol.http2, false); var inbound4 = GetInbound(_config.Inbound.First(), EInboundProtocol.http2, false);
inbound4.listen = listen; inbound4.listen = listen;
v2rayConfig.inbounds.Add(inbound4); v2rayConfig.inbounds.Add(inbound4);
//auth //auth
if (Utils.IsNotEmpty(_config.Inbound[0].User) && Utils.IsNotEmpty(_config.Inbound[0].Pass)) if (Utils.IsNotEmpty(_config.Inbound.First().User) && Utils.IsNotEmpty(_config.Inbound.First().Pass))
{ {
inbound3.settings.auth = "password"; inbound3.settings.auth = "password";
inbound3.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound[0].User, pass = _config.Inbound[0].Pass } }; inbound3.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound.First().User, pass = _config.Inbound.First().Pass } };
inbound4.settings.auth = "password"; inbound4.settings.auth = "password";
inbound4.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound[0].User, pass = _config.Inbound[0].Pass } }; inbound4.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound.First().User, pass = _config.Inbound.First().Pass } };
} }
} }
else else
@ -587,7 +587,7 @@ namespace ServiceLib.Services.CoreConfig
} }
else else
{ {
vnextItem = outbound.settings.vnext[0]; vnextItem = outbound.settings.vnext.First();
} }
vnextItem.address = node.Address; vnextItem.address = node.Address;
vnextItem.port = node.Port; vnextItem.port = node.Port;
@ -600,7 +600,7 @@ namespace ServiceLib.Services.CoreConfig
} }
else else
{ {
usersItem = vnextItem.users[0]; usersItem = vnextItem.users.First();
} }
//远程服务器用户ID //远程服务器用户ID
usersItem.id = node.Id; usersItem.id = node.Id;
@ -630,7 +630,7 @@ namespace ServiceLib.Services.CoreConfig
} }
else else
{ {
serversItem = outbound.settings.servers[0]; serversItem = outbound.settings.servers.First();
} }
serversItem.address = node.Address; serversItem.address = node.Address;
serversItem.port = node.Port; serversItem.port = node.Port;
@ -656,7 +656,7 @@ namespace ServiceLib.Services.CoreConfig
} }
else else
{ {
serversItem = outbound.settings.servers[0]; serversItem = outbound.settings.servers.First();
} }
serversItem.address = node.Address; serversItem.address = node.Address;
serversItem.port = node.Port; serversItem.port = node.Port;
@ -691,7 +691,7 @@ namespace ServiceLib.Services.CoreConfig
} }
else else
{ {
vnextItem = outbound.settings.vnext[0]; vnextItem = outbound.settings.vnext.First();
} }
vnextItem.address = node.Address; vnextItem.address = node.Address;
vnextItem.port = node.Port; vnextItem.port = node.Port;
@ -704,7 +704,7 @@ namespace ServiceLib.Services.CoreConfig
} }
else else
{ {
usersItem = vnextItem.users[0]; usersItem = vnextItem.users.First();
} }
usersItem.id = node.Id; usersItem.id = node.Id;
usersItem.email = Global.UserEMail; usersItem.email = Global.UserEMail;
@ -740,7 +740,7 @@ namespace ServiceLib.Services.CoreConfig
} }
else else
{ {
serversItem = outbound.settings.servers[0]; serversItem = outbound.settings.servers.First();
} }
serversItem.address = node.Address; serversItem.address = node.Address;
serversItem.port = node.Port; serversItem.port = node.Port;
@ -1167,7 +1167,7 @@ namespace ServiceLib.Services.CoreConfig
{ {
//fragment proxy //fragment proxy
if (_config.CoreBasicItem.EnableFragment if (_config.CoreBasicItem.EnableFragment
&& Utils.IsNotEmpty(v2rayConfig.outbounds[0].streamSettings?.security)) && Utils.IsNotEmpty(v2rayConfig.outbounds.First().streamSettings?.security))
{ {
var fragmentOutbound = new Outbounds4Ray var fragmentOutbound = new Outbounds4Ray
{ {
@ -1185,7 +1185,7 @@ namespace ServiceLib.Services.CoreConfig
}; };
v2rayConfig.outbounds.Add(fragmentOutbound); v2rayConfig.outbounds.Add(fragmentOutbound);
v2rayConfig.outbounds[0].streamSettings.sockopt = new() v2rayConfig.outbounds.First().streamSettings.sockopt = new()
{ {
dialerProxy = fragmentOutbound.tag dialerProxy = fragmentOutbound.tag
}; };
@ -1205,7 +1205,7 @@ namespace ServiceLib.Services.CoreConfig
} }
//current proxy //current proxy
var outbound = v2rayConfig.outbounds[0]; var outbound = v2rayConfig.outbounds.First();
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound); var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
//Previous proxy //Previous proxy

View file

@ -348,7 +348,7 @@ namespace ServiceLib.Services
if (!IPAddress.TryParse(url, out IPAddress? ipAddress)) if (!IPAddress.TryParse(url, out IPAddress? ipAddress))
{ {
IPHostEntry ipHostInfo = Dns.GetHostEntry(url); IPHostEntry ipHostInfo = Dns.GetHostEntry(url);
ipAddress = ipHostInfo.AddressList[0]; ipAddress = ipHostInfo.AddressList.First();
} }
var timer = Stopwatch.StartNew(); var timer = Stopwatch.StartNew();

View file

@ -21,9 +21,6 @@ namespace ServiceLib.ViewModels
[Reactive] [Reactive]
public string HostFilter { get; set; } public string HostFilter { get; set; }
[Reactive]
public int SortingSelected { get; set; }
[Reactive] [Reactive]
public bool AutoRefresh { get; set; } public bool AutoRefresh { get; set; }
@ -31,18 +28,12 @@ namespace ServiceLib.ViewModels
{ {
_config = AppHandler.Instance.Config; _config = AppHandler.Instance.Config;
_updateView = updateView; _updateView = updateView;
SortingSelected = _config.ClashUIItem.ConnectionsSorting;
AutoRefresh = _config.ClashUIItem.ConnectionsAutoRefresh; AutoRefresh = _config.ClashUIItem.ConnectionsAutoRefresh;
var canEditRemove = this.WhenAnyValue( var canEditRemove = this.WhenAnyValue(
x => x.SelectedSource, x => x.SelectedSource,
selectedSource => selectedSource != null && Utils.IsNotEmpty(selectedSource.Id)); selectedSource => selectedSource != null && Utils.IsNotEmpty(selectedSource.Id));
this.WhenAnyValue(
x => x.SortingSelected,
y => y >= 0)
.Subscribe(async c => await DoSortingSelected(c));
this.WhenAnyValue( this.WhenAnyValue(
x => x.AutoRefresh, x => x.AutoRefresh,
y => y == true) y => y == true)
@ -84,20 +75,6 @@ namespace ServiceLib.ViewModels
}); });
} }
private async Task DoSortingSelected(bool c)
{
if (!c)
{
return;
}
if (SortingSelected != _config.ClashUIItem.ConnectionsSorting)
{
_config.ClashUIItem.ConnectionsSorting = SortingSelected;
}
await GetClashConnections();
}
private async Task GetClashConnections() private async Task GetClashConnections()
{ {
var ret = await ClashApiHandler.Instance.GetClashConnectionsAsync(_config); var ret = await ClashApiHandler.Instance.GetClashConnectionsAsync(_config);
@ -115,7 +92,7 @@ namespace ServiceLib.ViewModels
var dtNow = DateTime.Now; var dtNow = DateTime.Now;
var lstModel = new List<ClashConnectionModel>(); var lstModel = new List<ClashConnectionModel>();
foreach (var item in connections ?? []) foreach (var item in connections ?? new())
{ {
var host = $"{(Utils.IsNullOrEmpty(item.metadata.host) ? item.metadata.destinationIP : item.metadata.host)}:{item.metadata.destinationPort}"; var host = $"{(Utils.IsNullOrEmpty(item.metadata.host) ? item.metadata.destinationIP : item.metadata.host)}:{item.metadata.destinationPort}";
if (HostFilter.IsNotEmpty() && !host.Contains(HostFilter)) if (HostFilter.IsNotEmpty() && !host.Contains(HostFilter))
@ -131,45 +108,14 @@ namespace ServiceLib.ViewModels
model.Host = host; model.Host = host;
var sp = (dtNow - item.start); var sp = (dtNow - item.start);
model.Time = sp.TotalSeconds < 0 ? 1 : sp.TotalSeconds; model.Time = sp.TotalSeconds < 0 ? 1 : sp.TotalSeconds;
model.Upload = item.upload;
model.Download = item.download;
model.UploadTraffic = $"{Utils.HumanFy((long)item.upload)}";
model.DownloadTraffic = $"{Utils.HumanFy((long)item.download)}";
model.Elapsed = sp.ToString(@"hh\:mm\:ss"); model.Elapsed = sp.ToString(@"hh\:mm\:ss");
model.Chain = item.chains?.Count > 0 ? item.chains[0] : string.Empty; item.chains?.Reverse();
model.Chain = $"{item.rule} , {string.Join("->", item.chains ?? new())}";
lstModel.Add(model); lstModel.Add(model);
} }
if (lstModel.Count <= 0) { return; } if (lstModel.Count <= 0) { return; }
//sort
switch (SortingSelected)
{
case 0:
lstModel = lstModel.OrderBy(t => t.Upload / t.Time).ToList();
break;
case 1:
lstModel = lstModel.OrderBy(t => t.Download / t.Time).ToList();
break;
case 2:
lstModel = lstModel.OrderBy(t => t.Upload).ToList();
break;
case 3:
lstModel = lstModel.OrderBy(t => t.Download).ToList();
break;
case 4:
lstModel = lstModel.OrderBy(t => t.Time).ToList();
break;
case 5:
lstModel = lstModel.OrderBy(t => t.Host).ToList();
break;
}
_connectionItems.AddRange(lstModel); _connectionItems.AddRange(lstModel);
} }

View file

@ -239,7 +239,7 @@ namespace ServiceLib.ViewModels
} }
else else
{ {
SelectedGroup = _proxyGroups[0]; SelectedGroup = _proxyGroups.First();
} }
} }
else else

View file

@ -122,7 +122,7 @@ namespace ServiceLib.ViewModels
#region Core #region Core
var inbound = _config.Inbound[0]; var inbound = _config.Inbound.First();
localPort = inbound.LocalPort; localPort = inbound.LocalPort;
udpEnabled = inbound.UdpEnabled; udpEnabled = inbound.UdpEnabled;
sniffingEnabled = inbound.SniffingEnabled; sniffingEnabled = inbound.SniffingEnabled;
@ -285,15 +285,15 @@ namespace ServiceLib.ViewModels
//} //}
//Core //Core
_config.Inbound[0].LocalPort = localPort; _config.Inbound.First().LocalPort = localPort;
_config.Inbound[0].UdpEnabled = udpEnabled; _config.Inbound.First().UdpEnabled = udpEnabled;
_config.Inbound[0].SniffingEnabled = sniffingEnabled; _config.Inbound.First().SniffingEnabled = sniffingEnabled;
_config.Inbound[0].DestOverride = destOverride?.ToList(); _config.Inbound.First().DestOverride = destOverride?.ToList();
_config.Inbound[0].RouteOnly = routeOnly; _config.Inbound.First().RouteOnly = routeOnly;
_config.Inbound[0].AllowLANConn = allowLANConn; _config.Inbound.First().AllowLANConn = allowLANConn;
_config.Inbound[0].NewPort4LAN = newPort4LAN; _config.Inbound.First().NewPort4LAN = newPort4LAN;
_config.Inbound[0].User = user; _config.Inbound.First().User = user;
_config.Inbound[0].Pass = pass; _config.Inbound.First().Pass = pass;
if (_config.Inbound.Count > 1) if (_config.Inbound.Count > 1)
{ {
_config.Inbound.RemoveAt(1); _config.Inbound.RemoveAt(1);

View file

@ -374,7 +374,7 @@ namespace ServiceLib.ViewModels
} }
else else
{ {
SelectedProfile = lstModel[0]; SelectedProfile = lstModel.First();
} }
} }
} }
@ -395,7 +395,7 @@ namespace ServiceLib.ViewModels
} }
else else
{ {
SelectedSub = _subItems[0]; SelectedSub = _subItems.First();
} }
} }

View file

@ -456,9 +456,9 @@ namespace ServiceLib.ViewModels
sb.Append($"[{EInboundProtocol.http}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.http)}]"); sb.Append($"[{EInboundProtocol.http}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.http)}]");
InboundDisplay = $"{ResUI.LabLocal}:{sb}"; InboundDisplay = $"{ResUI.LabLocal}:{sb}";
if (_config.Inbound[0].AllowLANConn) if (_config.Inbound.First().AllowLANConn)
{ {
if (_config.Inbound[0].NewPort4LAN) if (_config.Inbound.First().NewPort4LAN)
{ {
StringBuilder sb2 = new(); StringBuilder sb2 = new();
sb2.Append($"[{EInboundProtocol.socks}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks2)}]"); sb2.Append($"[{EInboundProtocol.socks}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks2)}]");

View file

@ -25,22 +25,6 @@
VerticalContentAlignment="Center" VerticalContentAlignment="Center"
Watermark="{x:Static resx:ResUI.ConnectionsHostFilterTitle}" /> Watermark="{x:Static resx:ResUI.ConnectionsHostFilterTitle}" />
<TextBlock
Margin="8,0"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSorting}" />
<ComboBox
x:Name="cmbSorting"
Width="100"
Margin="8,0">
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingUpSpeed}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingDownSpeed}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingUpTraffic}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingDownTraffic}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingTime}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingHost}" />
</ComboBox>
<Button <Button
x:Name="btnConnectionCloseAll" x:Name="btnConnectionCloseAll"
Width="30" Width="30"
@ -85,11 +69,11 @@
</DataGrid.ContextMenu> </DataGrid.ContextMenu>
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn <DataGridTextColumn
Width="240" Width="300"
Binding="{Binding Host}" Binding="{Binding Host}"
Header="{x:Static resx:ResUI.TbSortingHost}" /> Header="{x:Static resx:ResUI.TbSortingHost}" />
<DataGridTextColumn <DataGridTextColumn
Width="160" Width="500"
Binding="{Binding Chain}" Binding="{Binding Chain}"
Header="{x:Static resx:ResUI.TbSortingChain}" /> Header="{x:Static resx:ResUI.TbSortingChain}" />
<DataGridTextColumn <DataGridTextColumn
@ -97,17 +81,9 @@
Binding="{Binding Network}" Binding="{Binding Network}"
Header="{x:Static resx:ResUI.TbSortingNetwork}" /> Header="{x:Static resx:ResUI.TbSortingNetwork}" />
<DataGridTextColumn <DataGridTextColumn
Width="100" Width="160"
Binding="{Binding Type}" Binding="{Binding Type}"
Header="{x:Static resx:ResUI.TbSortingType}" /> Header="{x:Static resx:ResUI.TbSortingType}" />
<DataGridTextColumn
Width="100"
Binding="{Binding UploadTraffic}"
Header="{x:Static resx:ResUI.TbSortingUpTraffic}" />
<DataGridTextColumn
Width="100"
Binding="{Binding DownloadTraffic}"
Header="{x:Static resx:ResUI.TbSortingDownTraffic}" />
<DataGridTextColumn <DataGridTextColumn
Width="100" Width="100"
Binding="{Binding Elapsed}" Binding="{Binding Elapsed}"

View file

@ -22,7 +22,6 @@ namespace v2rayN.Desktop.Views
this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.menuConnectionCloseAll).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.menuConnectionCloseAll).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.HostFilter, v => v.txtHostFilter.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.HostFilter, v => v.txtHostFilter.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SortingSelected, v => v.cmbSorting.SelectedIndex).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.btnConnectionCloseAll).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.btnConnectionCloseAll).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables);
}); });

View file

@ -23,7 +23,7 @@ namespace v2rayN.Desktop.Views
{ {
clbdestOverride.Items.Add(it); clbdestOverride.Items.Add(it);
}); });
_config.Inbound[0].DestOverride?.ForEach(it => _config.Inbound.First().DestOverride?.ForEach(it =>
{ {
clbdestOverride.SelectedItems.Add(it); clbdestOverride.SelectedItems.Add(it);
}); });

View file

@ -1,11 +1,11 @@
<reactiveui:ReactiveUserControl <reactiveui:ReactiveUserControl
x:Class="v2rayN.Views.ClashConnectionsView" x:Class="v2rayN.Views.ClashConnectionsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:reactiveui="http://reactiveui.net"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib" xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
d:DesignHeight="450" d:DesignHeight="450"
@ -29,24 +29,6 @@
materialDesign:TextFieldAssist.HasClearButton="True" materialDesign:TextFieldAssist.HasClearButton="True"
Style="{StaticResource DefTextBox}" /> Style="{StaticResource DefTextBox}" />
<TextBlock
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSorting}" />
<ComboBox
x:Name="cmbSorting"
Width="100"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource DefComboBox}">
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingUpSpeed}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingDownSpeed}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingUpTraffic}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingDownTraffic}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingTime}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingHost}" />
</ComboBox>
<Button <Button
x:Name="btnConnectionCloseAll" x:Name="btnConnectionCloseAll"
Width="24" Width="24"
@ -88,11 +70,11 @@
</DataGrid.ContextMenu> </DataGrid.ContextMenu>
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn <DataGridTextColumn
Width="240" Width="300"
Binding="{Binding Host}" Binding="{Binding Host}"
Header="{x:Static resx:ResUI.TbSortingHost}" /> Header="{x:Static resx:ResUI.TbSortingHost}" />
<DataGridTextColumn <DataGridTextColumn
Width="160" Width="500"
Binding="{Binding Chain}" Binding="{Binding Chain}"
Header="{x:Static resx:ResUI.TbSortingChain}" /> Header="{x:Static resx:ResUI.TbSortingChain}" />
<DataGridTextColumn <DataGridTextColumn
@ -100,17 +82,9 @@
Binding="{Binding Network}" Binding="{Binding Network}"
Header="{x:Static resx:ResUI.TbSortingNetwork}" /> Header="{x:Static resx:ResUI.TbSortingNetwork}" />
<DataGridTextColumn <DataGridTextColumn
Width="100" Width="160"
Binding="{Binding Type}" Binding="{Binding Type}"
Header="{x:Static resx:ResUI.TbSortingType}" /> Header="{x:Static resx:ResUI.TbSortingType}" />
<DataGridTextColumn
Width="100"
Binding="{Binding UploadTraffic}"
Header="{x:Static resx:ResUI.TbSortingUpTraffic}" />
<DataGridTextColumn
Width="100"
Binding="{Binding DownloadTraffic}"
Header="{x:Static resx:ResUI.TbSortingDownTraffic}" />
<DataGridTextColumn <DataGridTextColumn
Width="100" Width="100"
Binding="{Binding Elapsed}" Binding="{Binding Elapsed}"

View file

@ -24,7 +24,6 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.menuConnectionCloseAll).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.menuConnectionCloseAll).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.HostFilter, v => v.txtHostFilter.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.HostFilter, v => v.txtHostFilter.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SortingSelected, v => v.cmbSorting.SelectedIndex).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.btnConnectionCloseAll).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.btnConnectionCloseAll).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables);
}); });

View file

@ -25,7 +25,7 @@ namespace v2rayN.Views
{ {
clbdestOverride.Items.Add(it); clbdestOverride.Items.Add(it);
}); });
_config.Inbound[0].DestOverride?.ForEach(it => _config.Inbound.First().DestOverride?.ForEach(it =>
{ {
clbdestOverride.SelectedItems.Add(it); clbdestOverride.SelectedItems.Add(it);
}); });
@ -211,7 +211,7 @@ namespace v2rayN.Views
{ {
files.AddRange(Directory.GetFiles(path, pattern)); files.AddRange(Directory.GetFiles(path, pattern));
} }
var culture = _config.UiItem.CurrentLanguage == Global.Languages[0] ? "zh-cn" : "en-us"; var culture = _config.UiItem.CurrentLanguage == Global.Languages.First() ? "zh-cn" : "en-us";
var culture2 = "en-us"; var culture2 = "en-us";
foreach (var ttf in files) foreach (var ttf in files)
{ {