Compare commits

...

27 Commits
6.58 ... 6.60

Author SHA1 Message Date
2dust
60a75d9a31 up 6.60 2024-09-23 17:23:23 +08:00
2dust
24566901fb up PackageReference 2024-09-23 17:22:14 +08:00
2dust
cc428618e5 Adjusting the text display 2024-09-23 17:17:12 +08:00
2dust
4d330cedac Disable auto update geo 2024-09-23 17:05:03 +08:00
2dust
2503583498 System proxy and tun mode
https://github.com/2dust/v2rayN/issues/5651
2024-09-23 17:03:28 +08:00
2dust
1b11916e1e Preparing to remove part of the core
https://github.com/2dust/v2rayN/discussions/5703
2024-09-23 15:16:32 +08:00
2dust
3dfd557265 Fix the problem of showing and hiding statistics columns 2024-09-23 15:00:25 +08:00
2dust
cd6bea28b6 Improved font display
https://github.com/2dust/v2rayN/issues/5713
2024-09-23 14:10:58 +08:00
2dust
054f0f2bc7 Bug fix
https://github.com/2dust/v2rayN/issues/5725
2024-09-23 13:37:18 +08:00
2dust
97347674e7 Bug fix
https://github.com/2dust/v2rayN/issues/5724
2024-09-23 12:09:17 +08:00
2dust
36d15852aa Setting up not to automatically update the GEO file on first run
https://github.com/2dust/v2rayN/issues/5704
2024-09-23 11:04:37 +08:00
2dust
4813610492 When running for the first time, switch the interface language to English when judging that the system language is not Chinese.
https://github.com/2dust/v2rayN/issues/5670
2024-09-23 11:01:03 +08:00
2dust
243dbab06a Fix ?! 2024-09-18 19:54:38 +08:00
2dust
073eaa9a26 Bug fix 2024-09-18 09:31:14 +08:00
2dust
cb1f936d05 Fix Speedtest bug 2024-09-17 18:41:01 +08:00
2dust
a7f3a7b1a7 up 6.59 2024-09-17 18:07:07 +08:00
2dust
71eb5f0813 HyperlinkButton Classes="WithIcon" 2024-09-17 17:26:01 +08:00
2dust
b4f50258a7 Fix style for desktop 2024-09-17 17:20:37 +08:00
2dust
346a9c5fcc Add Connections Host Filter 2024-09-17 16:59:35 +08:00
2dust
61635db5b5 Add IsNotEmpty function 2024-09-17 16:52:41 +08:00
2dust
4c0a59a715 Add Connections Host Filter
https://github.com/2dust/v2rayN/issues/5683
2024-09-17 14:50:31 +08:00
2dust
aa829a66ea Improved Style for Desktop version 2024-09-16 18:21:30 +08:00
2dust
885f193a00 Fix GetVersion 2024-09-16 15:34:35 +08:00
2dust
0a9bbf526d up PackageReference 2024-09-16 15:26:17 +08:00
2dust
ff6716b39d Restore backup file check 2024-09-16 15:23:06 +08:00
2dust
8505f2db96 Optimize backup
https://github.com/2dust/v2rayN/issues/5681
2024-09-16 13:37:38 +08:00
2dust
233d605256 Optimize the information function 2024-09-16 11:09:44 +08:00
97 changed files with 1022 additions and 908 deletions

View File

@@ -9,8 +9,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.28.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.65.0" />
<PackageReference Include="Google.Protobuf" Version="3.28.2" />
<PackageReference Include="Grpc.Net.Client" Version="2.66.0" />
<PackageReference Include="Grpc.Tools" Version="2.66.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -18,7 +18,7 @@ namespace ServiceLib.Common
Uri uri = new(url);
//Authorization Header
var headers = new WebHeaderCollection();
if (!Utils.IsNullOrEmpty(uri.UserInfo))
if (Utils.IsNotEmpty(uri.UserInfo))
{
headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo));
}

View File

@@ -82,7 +82,7 @@ namespace ServiceLib.Common
}
try
{
if (!Utils.IsNullOrEmpty(ignoredName) && entry.Name.Contains(ignoredName))
if (Utils.IsNotEmpty(ignoredName) && entry.Name.Contains(ignoredName))
{
continue;
}
@@ -102,6 +102,24 @@ namespace ServiceLib.Common
return true;
}
public static List<string>? GetFilesFromZip(string fileName)
{
if (!File.Exists(fileName))
{
return null;
}
try
{
using ZipArchive archive = ZipFile.OpenRead(fileName);
return archive.Entries.Select(entry => entry.FullName).ToList();
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
return null;
}
}
public static bool CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName)
{
try
@@ -139,7 +157,11 @@ namespace ServiceLib.Common
// Get the files in the source directory and copy to the destination directory
foreach (FileInfo file in dir.GetFiles())
{
if (!Utils.IsNullOrEmpty(ignoredName) && file.Name.Contains(ignoredName))
if (Utils.IsNotEmpty(ignoredName) && file.Name.Contains(ignoredName))
{
continue;
}
if (file.Extension == file.Name)
{
continue;
}

View File

@@ -22,7 +22,7 @@ namespace ServiceLib.Common
public async Task<string?> TryGetAsync(string url)
{
if (string.IsNullOrEmpty(url))
if (Utils.IsNullOrEmpty(url))
return null;
try

View File

@@ -15,11 +15,19 @@
this.version = $"{major}.{minor}.{patch}";
}
public SemanticVersion(string version)
public SemanticVersion(string? version)
{
this.version = version.RemovePrefix('v');
try
{
if (version.IsNullOrEmpty())
{
this.major = 0;
this.minor = 0;
this.patch = 0;
return;
}
this.version = version.RemovePrefix('v');
string[] parts = this.version.Split('.');
if (parts.Length == 2)
{
@@ -43,7 +51,6 @@
this.major = 0;
this.minor = 0;
this.patch = 0;
//this.version = "0.0.0";
}
}

View File

@@ -14,6 +14,11 @@ namespace ServiceLib.Common
return string.IsNullOrWhiteSpace(value);
}
public static bool IsNotEmpty([NotNullWhen(false)] this string? value)
{
return !string.IsNullOrEmpty(value);
}
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
{
if (s.IsNullOrEmpty()) return false;

View File

@@ -158,10 +158,11 @@ namespace ServiceLib.Common
/// </summary>
/// <param name="plainText"></param>
/// <returns></returns>
public static string Base64Decode(string plainText)
public static string Base64Decode(string? plainText)
{
try
{
if (plainText.IsNullOrEmpty()) return "";
plainText = plainText.Trim()
.Replace(Environment.NewLine, "")
.Replace("\n", "")
@@ -365,7 +366,7 @@ namespace ServiceLib.Common
}
}
public static bool IsBase64String(string plainText)
public static bool IsBase64String(string? plainText)
{
if (plainText.IsNullOrEmpty()) return false;
var buffer = new Span<byte>(new byte[plainText.Length]);
@@ -417,6 +418,11 @@ namespace ServiceLib.Common
return false;
}
public static bool IsNotEmpty(string? text)
{
return !string.IsNullOrEmpty(text);
}
/// <summary>
/// 验证IP地址是否合法
/// </summary>
@@ -567,13 +573,12 @@ namespace ServiceLib.Common
{
try
{
string location = GetExePath();
if (blFull)
{
return string.Format("{0} - V{1} - {2}",
Global.AppName,
GetVersionInfo(),
File.GetLastWriteTime(location).ToString("yyyy/MM/dd"));
File.GetLastWriteTime(GetExePath()).ToString("yyyy/MM/dd"));
}
else
{
@@ -593,7 +598,7 @@ namespace ServiceLib.Common
{
try
{
return Assembly.GetExecutingAssembly()?.GetName()?.Version?.ToString() ?? "0.0";
return Assembly.GetExecutingAssembly()?.GetName()?.Version?.ToString(3) ?? "0.0";
}
catch (Exception ex)
{
@@ -808,7 +813,7 @@ namespace ServiceLib.Common
}
if (coreType != null)
{
_tempPath = Path.Combine(_tempPath, coreType.ToString()!);
_tempPath = Path.Combine(_tempPath, coreType.ToString());
if (!Directory.Exists(_tempPath))
{
Directory.CreateDirectory(_tempPath);

View File

@@ -5,12 +5,12 @@
VMess = 1,
Custom = 2,
Shadowsocks = 3,
Socks = 4,
SOCKS = 4,
VLESS = 5,
Trojan = 6,
Hysteria2 = 7,
Tuic = 8,
Wireguard = 9,
Http = 10
TUIC = 8,
WireGuard = 9,
HTTP = 10
}
}

View File

@@ -137,25 +137,25 @@
{
{EConfigType.VMess,"vmess://"},
{EConfigType.Shadowsocks,"ss://"},
{EConfigType.Socks,"socks://"},
{EConfigType.SOCKS,"socks://"},
{EConfigType.VLESS,"vless://"},
{EConfigType.Trojan,"trojan://"},
{EConfigType.Hysteria2,"hysteria2://"},
{EConfigType.Tuic,"tuic://"},
{EConfigType.Wireguard,"wireguard://"}
{EConfigType.TUIC,"tuic://"},
{EConfigType.WireGuard,"wireguard://"}
};
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
{
{EConfigType.VMess,"vmess"},
{EConfigType.Shadowsocks,"shadowsocks"},
{EConfigType.Socks,"socks"},
{EConfigType.Http,"http"},
{EConfigType.SOCKS,"socks"},
{EConfigType.HTTP,"http"},
{EConfigType.VLESS,"vless"},
{EConfigType.Trojan,"trojan"},
{EConfigType.Hysteria2,"hysteria2"},
{EConfigType.Tuic,"tuic"},
{EConfigType.Wireguard,"wireguard"}
{EConfigType.TUIC,"tuic"},
{EConfigType.WireGuard,"wireguard"}
};
public static readonly List<string> VmessSecurities = new() { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" };
@@ -166,7 +166,7 @@
public static readonly List<string> Flows = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
public static readonly List<string> Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "splithttp", "h2", "quic", "grpc" };
public static readonly List<string> KcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
public static readonly List<string> CoreTypes = new() { "v2fly", "SagerNet", "Xray", "sing_box" };
public static readonly List<string> CoreTypes = new() { "v2fly", "Xray", "sing_box" };//TODO
public static readonly List<string> CoreTypes4VLESS = new() { "Xray", "sing_box" };
public static readonly List<string> DomainStrategies = new() { "AsIs", "IPIfNonMatch", "IPOnDemand" };
public static readonly List<string> DomainStrategies4Singbox = new() { "ipv4_only", "ipv6_only", "prefer_ipv4", "prefer_ipv6", "" };

View File

@@ -23,7 +23,7 @@ namespace ServiceLib.Handler
{
//载入配置文件
var result = Utils.LoadResource(Utils.GetConfigPath(configRes));
if (!Utils.IsNullOrEmpty(result))
if (Utils.IsNotEmpty(result))
{
//转成Json
config = JsonUtils.Deserialize<Config>(result);
@@ -140,7 +140,14 @@ namespace ServiceLib.Handler
}
if (Utils.IsNullOrEmpty(config.uiItem.currentLanguage))
{
config.uiItem.currentLanguage = Global.Languages[0];
if (Thread.CurrentThread.CurrentCulture.Name.Equals("zh-cn", StringComparison.CurrentCultureIgnoreCase))
{
config.uiItem.currentLanguage = Global.Languages[0];
}
else
{
config.uiItem.currentLanguage = Global.Languages[2];
}
}
if (config.constItem == null)
@@ -394,13 +401,13 @@ namespace ServiceLib.Handler
{
EConfigType.VMess => AddVMessServer(config, item),
EConfigType.Shadowsocks => AddShadowsocksServer(config, item),
EConfigType.Socks => AddSocksServer(config, item),
EConfigType.Http => AddHttpServer(config, item),
EConfigType.SOCKS => AddSocksServer(config, item),
EConfigType.HTTP => AddHttpServer(config, item),
EConfigType.Trojan => AddTrojanServer(config, item),
EConfigType.VLESS => AddVlessServer(config, item),
EConfigType.Hysteria2 => AddHysteria2Server(config, item),
EConfigType.Tuic => AddTuicServer(config, item),
EConfigType.Wireguard => AddWireguardServer(config, item),
EConfigType.TUIC => AddTuicServer(config, item),
EConfigType.WireGuard => AddWireguardServer(config, item),
_ => -1,
};
return ret;
@@ -732,7 +739,7 @@ namespace ServiceLib.Handler
/// <returns></returns>
public static int AddSocksServer(Config config, ProfileItem profileItem, bool toFile = true)
{
profileItem.configType = EConfigType.Socks;
profileItem.configType = EConfigType.SOCKS;
profileItem.address = profileItem.address.TrimEx();
@@ -749,7 +756,7 @@ namespace ServiceLib.Handler
/// <returns></returns>
public static int AddHttpServer(Config config, ProfileItem profileItem, bool toFile = true)
{
profileItem.configType = EConfigType.Http;
profileItem.configType = EConfigType.HTTP;
profileItem.address = profileItem.address.TrimEx();
@@ -822,7 +829,7 @@ namespace ServiceLib.Handler
/// <returns></returns>
public static int AddTuicServer(Config config, ProfileItem profileItem, bool toFile = true)
{
profileItem.configType = EConfigType.Tuic;
profileItem.configType = EConfigType.TUIC;
profileItem.coreType = ECoreType.sing_box;
profileItem.address = profileItem.address.TrimEx();
@@ -861,7 +868,7 @@ namespace ServiceLib.Handler
/// <returns></returns>
public static int AddWireguardServer(Config config, ProfileItem profileItem, bool toFile = true)
{
profileItem.configType = EConfigType.Wireguard;
profileItem.configType = EConfigType.WireGuard;
profileItem.coreType = ECoreType.sing_box;
profileItem.address = profileItem.address.TrimEx();
@@ -1007,7 +1014,7 @@ namespace ServiceLib.Handler
{
return -1;
}
if (!Utils.IsNullOrEmpty(profileItem.security) && profileItem.security != Global.None)
if (Utils.IsNotEmpty(profileItem.security) && profileItem.security != Global.None)
{
profileItem.security = Global.None;
}
@@ -1045,7 +1052,7 @@ namespace ServiceLib.Handler
{
profileItem.configVersion = 2;
if (!Utils.IsNullOrEmpty(profileItem.streamSecurity))
if (Utils.IsNotEmpty(profileItem.streamSecurity))
{
if (profileItem.streamSecurity != Global.StreamSecurity
&& profileItem.streamSecurity != Global.StreamSecurityReality)
@@ -1065,7 +1072,7 @@ namespace ServiceLib.Handler
}
}
if (!Utils.IsNullOrEmpty(profileItem.network) && !Global.Networks.Contains(profileItem.network))
if (Utils.IsNotEmpty(profileItem.network) && !Global.Networks.Contains(profileItem.network))
{
profileItem.network = Global.DefaultNetwork;
}
@@ -1186,7 +1193,7 @@ namespace ServiceLib.Handler
string subFilter = string.Empty;
//remove sub items
if (isSub && !Utils.IsNullOrEmpty(subid))
if (isSub && Utils.IsNotEmpty(subid))
{
RemoveServerViaSubid(config, subid, isSub);
subFilter = LazyConfig.Instance.GetSubItem(subid)?.filter ?? "";
@@ -1219,7 +1226,7 @@ namespace ServiceLib.Handler
}
//exist sub items
if (isSub && !Utils.IsNullOrEmpty(subid))
if (isSub && Utils.IsNotEmpty(subid))
{
var existItem = lstOriSub?.FirstOrDefault(t => t.isSub == isSub
&& config.uiItem.enableUpdateSubOnlyRemarksExist ? t.remarks == profileItem.remarks : CompareProfileItem(t, profileItem, true));
@@ -1241,7 +1248,7 @@ namespace ServiceLib.Handler
}
}
//filter
if (!Utils.IsNullOrEmpty(subFilter))
if (Utils.IsNotEmpty(subFilter))
{
if (!Regex.IsMatch(profileItem.remarks, subFilter))
{
@@ -1256,12 +1263,12 @@ namespace ServiceLib.Handler
{
EConfigType.VMess => AddVMessServer(config, profileItem, false),
EConfigType.Shadowsocks => AddShadowsocksServer(config, profileItem, false),
EConfigType.Socks => AddSocksServer(config, profileItem, false),
EConfigType.SOCKS => AddSocksServer(config, profileItem, false),
EConfigType.Trojan => AddTrojanServer(config, profileItem, false),
EConfigType.VLESS => AddVlessServer(config, profileItem, false),
EConfigType.Hysteria2 => AddHysteria2Server(config, profileItem, false),
EConfigType.Tuic => AddTuicServer(config, profileItem, false),
EConfigType.Wireguard => AddWireguardServer(config, profileItem, false),
EConfigType.TUIC => AddTuicServer(config, profileItem, false),
EConfigType.WireGuard => AddWireguardServer(config, profileItem, false),
_ => -1,
};
@@ -1305,7 +1312,7 @@ namespace ServiceLib.Handler
}
if (lstProfiles != null && lstProfiles.Count > 0)
{
if (isSub && !Utils.IsNullOrEmpty(subid))
if (isSub && Utils.IsNotEmpty(subid))
{
RemoveServerViaSubid(config, subid, isSub);
}
@@ -1361,7 +1368,7 @@ namespace ServiceLib.Handler
return -1;
}
if (isSub && !Utils.IsNullOrEmpty(subid))
if (isSub && Utils.IsNotEmpty(subid))
{
RemoveServerViaSubid(config, subid, isSub);
}
@@ -1389,7 +1396,7 @@ namespace ServiceLib.Handler
return -1;
}
if (isSub && !Utils.IsNullOrEmpty(subid))
if (isSub && Utils.IsNotEmpty(subid))
{
RemoveServerViaSubid(config, subid, isSub);
}
@@ -1421,7 +1428,7 @@ namespace ServiceLib.Handler
return -1;
}
List<ProfileItem>? lstOriSub = null;
if (isSub && !Utils.IsNullOrEmpty(subid))
if (isSub && Utils.IsNotEmpty(subid))
{
lstOriSub = LazyConfig.Instance.ProfileItems(subid);
}

View File

@@ -43,7 +43,7 @@
}
string addressFileName = node.address;
if (string.IsNullOrEmpty(addressFileName))
if (Utils.IsNullOrEmpty(addressFileName))
{
msg = ResUI.FailedGetDefaultConfiguration;
return -1;
@@ -117,7 +117,7 @@
if (_config.tunModeItem.enableTun)
{
string tun = Utils.GetEmbedText(Global.ClashTunYaml);
if (!string.IsNullOrEmpty(tun))
if (Utils.IsNotEmpty(tun))
{
var tunContent = YamlUtils.FromYaml<Dictionary<string, object>>(tun);
if (tunContent != null)

View File

@@ -132,10 +132,10 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (it.configType is EConfigType.VMess or EConfigType.VLESS)
{
var item2 = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item2 is null || Utils.IsNullOrEmpty(item2.id) || !Utils.IsGuidByParse(item2.id))
if (item is null || Utils.IsNullOrEmpty(item.id) || !Utils.IsGuidByParse(item.id))
{
continue;
}
@@ -178,7 +178,6 @@ namespace ServiceLib.Handler.CoreConfig
singboxConfig.inbounds.Add(inbound);
//outbound
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null)
{
continue;
@@ -193,6 +192,12 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
if ((it.configType is EConfigType.VLESS or EConfigType.Trojan)
&& item.streamSecurity == Global.StreamSecurityReality
&& item.publicKey.IsNullOrEmpty())
{
continue;
}
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
GenOutbound(item, outbound);
@@ -370,7 +375,7 @@ namespace ServiceLib.Handler.CoreConfig
}
string addressFileName = node.address;
if (string.IsNullOrEmpty(addressFileName))
if (Utils.IsNullOrEmpty(addressFileName))
{
msg = ResUI.FailedGetDefaultConfiguration;
return -1;
@@ -489,7 +494,7 @@ namespace ServiceLib.Handler.CoreConfig
if (_config.routingBasicItem.enableRoutingAdvanced)
{
var routing = ConfigHandler.GetDefaultRouting(_config);
if (!Utils.IsNullOrEmpty(routing.domainStrategy4Singbox))
if (Utils.IsNotEmpty(routing.domainStrategy4Singbox))
{
inbound.domain_strategy = routing.domainStrategy4Singbox;
}
@@ -512,7 +517,7 @@ namespace ServiceLib.Handler.CoreConfig
singboxConfig.inbounds.Add(inbound4);
//auth
if (!Utils.IsNullOrEmpty(_config.inbound[0].user) && !Utils.IsNullOrEmpty(_config.inbound[0].pass))
if (Utils.IsNotEmpty(_config.inbound[0].user) && Utils.IsNotEmpty(_config.inbound[0].pass))
{
inbound3.users = new() { new() { username = _config.inbound[0].user, password = _config.inbound[0].pass } };
inbound4.users = new() { new() { username = _config.inbound[0].user, password = _config.inbound[0].pass } };
@@ -601,21 +606,21 @@ namespace ServiceLib.Handler.CoreConfig
GenOutboundMux(node, outbound);
break;
}
case EConfigType.Socks:
case EConfigType.SOCKS:
{
outbound.version = "5";
if (!Utils.IsNullOrEmpty(node.security)
&& !Utils.IsNullOrEmpty(node.id))
if (Utils.IsNotEmpty(node.security)
&& Utils.IsNotEmpty(node.id))
{
outbound.username = node.security;
outbound.password = node.id;
}
break;
}
case EConfigType.Http:
case EConfigType.HTTP:
{
if (!Utils.IsNullOrEmpty(node.security)
&& !Utils.IsNullOrEmpty(node.id))
if (Utils.IsNotEmpty(node.security)
&& Utils.IsNotEmpty(node.id))
{
outbound.username = node.security;
outbound.password = node.id;
@@ -649,7 +654,7 @@ namespace ServiceLib.Handler.CoreConfig
{
outbound.password = node.id;
if (!Utils.IsNullOrEmpty(node.path))
if (Utils.IsNotEmpty(node.path))
{
outbound.obfs = new()
{
@@ -662,14 +667,14 @@ namespace ServiceLib.Handler.CoreConfig
outbound.down_mbps = _config.hysteriaItem.down_mbps > 0 ? _config.hysteriaItem.down_mbps : null;
break;
}
case EConfigType.Tuic:
case EConfigType.TUIC:
{
outbound.uuid = node.id;
outbound.password = node.security;
outbound.congestion_control = node.headerType;
break;
}
case EConfigType.Wireguard:
case EConfigType.WireGuard:
{
outbound.private_key = node.id;
outbound.peer_public_key = node.publicKey;
@@ -695,7 +700,7 @@ namespace ServiceLib.Handler.CoreConfig
{
try
{
if (_config.coreBasicItem.muxEnabled && !Utils.IsNullOrEmpty(_config.mux4SboxItem.protocol))
if (_config.coreBasicItem.muxEnabled && Utils.IsNotEmpty(_config.mux4SboxItem.protocol))
{
var mux = new Multiplex4Sbox()
{
@@ -721,11 +726,11 @@ namespace ServiceLib.Handler.CoreConfig
if (node.streamSecurity == Global.StreamSecurityReality || node.streamSecurity == Global.StreamSecurity)
{
var server_name = string.Empty;
if (!Utils.IsNullOrEmpty(node.sni))
if (Utils.IsNotEmpty(node.sni))
{
server_name = node.sni;
}
else if (!Utils.IsNullOrEmpty(node.requestHost))
else if (Utils.IsNotEmpty(node.requestHost))
{
server_name = Utils.String2List(node.requestHost)[0];
}
@@ -736,7 +741,7 @@ namespace ServiceLib.Handler.CoreConfig
insecure = Utils.ToBool(node.allowInsecure.IsNullOrEmpty() ? _config.coreBasicItem.defAllowInsecure.ToString().ToLower() : node.allowInsecure),
alpn = node.GetAlpn(),
};
if (!Utils.IsNullOrEmpty(node.fingerprint))
if (Utils.IsNotEmpty(node.fingerprint))
{
tls.utls = new Utls4Sbox()
{
@@ -798,7 +803,7 @@ namespace ServiceLib.Handler.CoreConfig
case nameof(ETransport.ws):
transport.type = nameof(ETransport.ws);
transport.path = Utils.IsNullOrEmpty(node.path) ? null : node.path;
if (!Utils.IsNullOrEmpty(node.requestHost))
if (Utils.IsNotEmpty(node.requestHost))
{
transport.headers = new()
{
@@ -860,7 +865,7 @@ namespace ServiceLib.Handler.CoreConfig
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
//Previous proxy
var prevNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.prevProfile!);
var prevNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.prevProfile);
if (prevNode is not null
&& prevNode.configType != EConfigType.Custom)
{
@@ -873,7 +878,7 @@ namespace ServiceLib.Handler.CoreConfig
}
//Next proxy
var nextNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.nextProfile!);
var nextNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.nextProfile);
if (nextNode is not null
&& nextNode.configType != EConfigType.Custom)
{
@@ -951,7 +956,7 @@ namespace ServiceLib.Handler.CoreConfig
if (routing != null)
{
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.ruleSet);
foreach (var item in rules!)
foreach (var item in rules ?? [])
{
if (item.enabled)
{
@@ -966,7 +971,7 @@ namespace ServiceLib.Handler.CoreConfig
if (lockedItem != null)
{
var rules = JsonUtils.Deserialize<List<RulesItem>>(lockedItem.ruleSet);
foreach (var item in rules!)
foreach (var item in rules ?? [])
{
GenRoutingUserRule(item, singboxConfig.route.rules);
}
@@ -1020,7 +1025,7 @@ namespace ServiceLib.Handler.CoreConfig
outbound = item.outboundTag,
};
if (!Utils.IsNullOrEmpty(item.port))
if (Utils.IsNotEmpty(item.port))
{
if (item.port.Contains("-"))
{
@@ -1031,7 +1036,7 @@ namespace ServiceLib.Handler.CoreConfig
rule.port = new List<int> { Utils.ToInt(item.port) };
}
}
if (!Utils.IsNullOrEmpty(item.network))
if (Utils.IsNotEmpty(item.network))
{
rule.network = Utils.String2List(item.network);
}
@@ -1221,7 +1226,7 @@ namespace ServiceLib.Handler.CoreConfig
});
var lstDomain = singboxConfig.outbounds
.Where(t => !Utils.IsNullOrEmpty(t.server) && Utils.IsDomain(t.server))
.Where(t => Utils.IsNotEmpty(t.server) && Utils.IsDomain(t.server))
.Select(t => t.server)
.Distinct()
.ToList();
@@ -1235,7 +1240,7 @@ namespace ServiceLib.Handler.CoreConfig
}
//Tun2SocksAddress
if (_config.tunModeItem.enableTun && node?.configType == EConfigType.Socks && Utils.IsDomain(node?.sni))
if (_config.tunModeItem.enableTun && node?.configType == EConfigType.SOCKS && Utils.IsDomain(node?.sni))
{
dns4Sbox.rules.Insert(0, new()
{
@@ -1324,10 +1329,10 @@ namespace ServiceLib.Handler.CoreConfig
if (_config.routingBasicItem.enableRoutingAdvanced)
{
var routing = ConfigHandler.GetDefaultRouting(_config);
if (!Utils.IsNullOrEmpty(routing.customRulesetPath4Singbox))
if (Utils.IsNotEmpty(routing.customRulesetPath4Singbox))
{
var result = Utils.LoadResource(routing.customRulesetPath4Singbox);
if (!Utils.IsNullOrEmpty(result))
if (Utils.IsNotEmpty(result))
{
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
.Where(t => t.tag != null)

View File

@@ -110,7 +110,7 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
if (it.configType is EConfigType.Hysteria2 or EConfigType.Tuic or EConfigType.Wireguard)
if (it.configType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard)
{
continue;
}
@@ -248,10 +248,10 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (it.configType is EConfigType.VMess or EConfigType.VLESS)
{
var item2 = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item2 is null || Utils.IsNullOrEmpty(item2.id) || !Utils.IsGuidByParse(item2.id))
if (item is null || Utils.IsNullOrEmpty(item.id) || !Utils.IsGuidByParse(item.id))
{
continue;
}
@@ -294,7 +294,6 @@ namespace ServiceLib.Handler.CoreConfig
v2rayConfig.inbounds.Add(inbound);
//outbound
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null)
{
continue;
@@ -309,6 +308,12 @@ namespace ServiceLib.Handler.CoreConfig
{
continue;
}
if ((it.configType is EConfigType.VLESS or EConfigType.Trojan)
&& item.streamSecurity == Global.StreamSecurityReality
&& item.publicKey.IsNullOrEmpty())
{
continue;
}
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
GenOutbound(item, outbound);
@@ -392,7 +397,7 @@ namespace ServiceLib.Handler.CoreConfig
v2rayConfig.inbounds.Add(inbound4);
//auth
if (!Utils.IsNullOrEmpty(_config.inbound[0].user) && !Utils.IsNullOrEmpty(_config.inbound[0].pass))
if (Utils.IsNotEmpty(_config.inbound[0].user) && Utils.IsNotEmpty(_config.inbound[0].pass))
{
inbound3.settings.auth = "password";
inbound3.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.inbound[0].user, pass = _config.inbound[0].pass } };
@@ -453,7 +458,7 @@ namespace ServiceLib.Handler.CoreConfig
var routing = ConfigHandler.GetDefaultRouting(_config);
if (routing != null)
{
if (!Utils.IsNullOrEmpty(routing.domainStrategy))
if (Utils.IsNotEmpty(routing.domainStrategy))
{
v2rayConfig.routing.domainStrategy = routing.domainStrategy;
}
@@ -550,7 +555,7 @@ namespace ServiceLib.Handler.CoreConfig
}
if (!hasDomainIp)
{
if (!Utils.IsNullOrEmpty(rule.port)
if (Utils.IsNotEmpty(rule.port)
|| rule.protocol?.Count > 0
|| rule.inboundTag?.Count > 0
)
@@ -642,8 +647,8 @@ namespace ServiceLib.Handler.CoreConfig
outbound.settings.vnext = null;
break;
}
case EConfigType.Socks:
case EConfigType.Http:
case EConfigType.SOCKS:
case EConfigType.HTTP:
{
ServersItem4Ray serversItem;
if (outbound.settings.servers.Count <= 0)
@@ -660,8 +665,8 @@ namespace ServiceLib.Handler.CoreConfig
serversItem.method = null;
serversItem.password = null;
if (!Utils.IsNullOrEmpty(node.security)
&& !Utils.IsNullOrEmpty(node.id))
if (Utils.IsNotEmpty(node.security)
&& Utils.IsNotEmpty(node.id))
{
SocksUsersItem4Ray socksUsersItem = new()
{
@@ -712,7 +717,7 @@ namespace ServiceLib.Handler.CoreConfig
if (node.streamSecurity == Global.StreamSecurityReality
|| node.streamSecurity == Global.StreamSecurity)
{
if (!Utils.IsNullOrEmpty(node.flow))
if (Utils.IsNotEmpty(node.flow))
{
usersItem.flow = node.flow;
@@ -818,11 +823,11 @@ namespace ServiceLib.Handler.CoreConfig
alpn = node.GetAlpn(),
fingerprint = node.fingerprint.IsNullOrEmpty() ? _config.coreBasicItem.defFingerprint : node.fingerprint
};
if (!Utils.IsNullOrEmpty(sni))
if (Utils.IsNotEmpty(sni))
{
tlsSettings.serverName = sni;
}
else if (!Utils.IsNullOrEmpty(host))
else if (Utils.IsNotEmpty(host))
{
tlsSettings.serverName = Utils.String2List(host)[0];
}
@@ -867,7 +872,7 @@ namespace ServiceLib.Handler.CoreConfig
{
type = node.headerType
};
if (!Utils.IsNullOrEmpty(node.path))
if (Utils.IsNotEmpty(node.path))
{
kcpSettings.seed = node.path;
}
@@ -878,15 +883,15 @@ namespace ServiceLib.Handler.CoreConfig
WsSettings4Ray wsSettings = new();
wsSettings.headers = new Headers4Ray();
string path = node.path;
if (!Utils.IsNullOrEmpty(host))
if (Utils.IsNotEmpty(host))
{
wsSettings.headers.Host = host;
}
if (!Utils.IsNullOrEmpty(path))
if (Utils.IsNotEmpty(path))
{
wsSettings.path = path;
}
if (!Utils.IsNullOrEmpty(useragent))
if (Utils.IsNotEmpty(useragent))
{
wsSettings.headers.UserAgent = useragent;
}
@@ -897,11 +902,11 @@ namespace ServiceLib.Handler.CoreConfig
case nameof(ETransport.httpupgrade):
HttpupgradeSettings4Ray httpupgradeSettings = new();
if (!Utils.IsNullOrEmpty(node.path))
if (Utils.IsNotEmpty(node.path))
{
httpupgradeSettings.path = node.path;
}
if (!Utils.IsNullOrEmpty(host))
if (Utils.IsNotEmpty(host))
{
httpupgradeSettings.host = host;
}
@@ -916,11 +921,11 @@ namespace ServiceLib.Handler.CoreConfig
maxConcurrentUploads = 10
};
if (!Utils.IsNullOrEmpty(node.path))
if (Utils.IsNotEmpty(node.path))
{
splithttpSettings.path = node.path;
}
if (!Utils.IsNullOrEmpty(host))
if (Utils.IsNotEmpty(host))
{
splithttpSettings.host = host;
}
@@ -931,7 +936,7 @@ namespace ServiceLib.Handler.CoreConfig
case nameof(ETransport.h2):
HttpSettings4Ray httpSettings = new();
if (!Utils.IsNullOrEmpty(host))
if (Utils.IsNotEmpty(host))
{
httpSettings.host = Utils.String2List(host);
}
@@ -954,7 +959,7 @@ namespace ServiceLib.Handler.CoreConfig
streamSettings.quicSettings = quicsettings;
if (node.streamSecurity == Global.StreamSecurity)
{
if (!Utils.IsNullOrEmpty(sni))
if (Utils.IsNotEmpty(sni))
{
streamSettings.tlsSettings.serverName = sni;
}
@@ -1000,7 +1005,7 @@ namespace ServiceLib.Handler.CoreConfig
request = request.Replace("$requestUserAgent$", $"\"{useragent}\"");
//Path
string pathHttp = @"/";
if (!Utils.IsNullOrEmpty(node.path))
if (Utils.IsNotEmpty(node.path))
{
string[] arrPath = node.path.Split(',');
pathHttp = string.Join("\",\"", arrPath);
@@ -1033,7 +1038,7 @@ namespace ServiceLib.Handler.CoreConfig
}
//Outbound Freedom domainStrategy
if (!Utils.IsNullOrEmpty(domainStrategy4Freedom))
if (Utils.IsNotEmpty(domainStrategy4Freedom))
{
var outbound = v2rayConfig.outbounds[1];
outbound.settings.domainStrategy = domainStrategy4Freedom;
@@ -1157,7 +1162,7 @@ namespace ServiceLib.Handler.CoreConfig
{
//fragment proxy
if (_config.coreBasicItem.enableFragment
&& !Utils.IsNullOrEmpty(v2rayConfig.outbounds[0].streamSettings?.security))
&& Utils.IsNotEmpty(v2rayConfig.outbounds[0].streamSettings?.security))
{
var fragmentOutbound = new Outbounds4Ray
{
@@ -1199,12 +1204,12 @@ namespace ServiceLib.Handler.CoreConfig
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
//Previous proxy
var prevNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.prevProfile!);
var prevNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.prevProfile);
if (prevNode is not null
&& prevNode.configType != EConfigType.Custom
&& prevNode.configType != EConfigType.Hysteria2
&& prevNode.configType != EConfigType.Tuic
&& prevNode.configType != EConfigType.Wireguard)
&& prevNode.configType != EConfigType.TUIC
&& prevNode.configType != EConfigType.WireGuard)
{
var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
GenOutbound(prevNode, prevOutbound);
@@ -1218,12 +1223,12 @@ namespace ServiceLib.Handler.CoreConfig
}
//Next proxy
var nextNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.nextProfile!);
var nextNode = LazyConfig.Instance.GetProfileItemViaRemarks(subItem.nextProfile);
if (nextNode is not null
&& nextNode.configType != EConfigType.Custom
&& nextNode.configType != EConfigType.Hysteria2
&& nextNode.configType != EConfigType.Tuic
&& nextNode.configType != EConfigType.Wireguard)
&& nextNode.configType != EConfigType.TUIC
&& nextNode.configType != EConfigType.WireGuard)
{
var nextOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
GenOutbound(nextNode, nextOutbound);

View File

@@ -66,7 +66,7 @@ namespace ServiceLib.Handler
public int LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
{
int pid = -1;
var coreType = selecteds.Exists(t => t.configType == EConfigType.Hysteria2 || t.configType == EConfigType.Tuic || t.configType == EConfigType.Wireguard) ? ECoreType.sing_box : ECoreType.Xray;
var coreType = selecteds.Exists(t => t.configType == EConfigType.Hysteria2 || t.configType == EConfigType.TUIC || t.configType == EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray;
string configPath = Utils.GetConfigPath(Global.CoreSpeedtestConfigFileName);
if (CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType, out string msg) != 0)
{
@@ -204,7 +204,7 @@ namespace ServiceLib.Handler
itemSocks = new ProfileItem()
{
coreType = preCoreType,
configType = EConfigType.Socks,
configType = EConfigType.SOCKS,
address = Global.Loopback,
sni = node.address, //Tun2SocksAddress
port = LazyConfig.Instance.GetLocalPort(EInboundProtocol.socks)
@@ -216,7 +216,7 @@ namespace ServiceLib.Handler
itemSocks = new ProfileItem()
{
coreType = preCoreType,
configType = EConfigType.Socks,
configType = EConfigType.SOCKS,
address = Global.Loopback,
port = node.preSocksPort.Value,
};
@@ -302,7 +302,7 @@ namespace ServiceLib.Handler
{
proc.OutputDataReceived += (sender, e) =>
{
if (!Utils.IsNullOrEmpty(e.Data))
if (Utils.IsNotEmpty(e.Data))
{
string msg = e.Data + Environment.NewLine;
ShowMsg(false, msg);
@@ -310,7 +310,7 @@ namespace ServiceLib.Handler
};
proc.ErrorDataReceived += (sender, e) =>
{
if (!Utils.IsNullOrEmpty(e.Data))
if (Utils.IsNotEmpty(e.Data))
{
string msg = e.Data + Environment.NewLine;
ShowMsg(false, msg);

View File

@@ -117,7 +117,7 @@ namespace ServiceLib.Handler
try
{
var result1 = await DownloadStringAsync(url, blProxy, userAgent);
if (!Utils.IsNullOrEmpty(result1))
if (Utils.IsNotEmpty(result1))
{
return result1;
}
@@ -135,7 +135,7 @@ namespace ServiceLib.Handler
try
{
var result2 = await DownloadStringViaDownloader(url, blProxy, userAgent);
if (!Utils.IsNullOrEmpty(result2))
if (Utils.IsNotEmpty(result2))
{
return result2;
}
@@ -155,7 +155,7 @@ namespace ServiceLib.Handler
using var wc = new WebClient();
wc.Proxy = GetWebProxy(blProxy);
var result3 = await wc.DownloadStringTaskAsync(url);
if (!Utils.IsNullOrEmpty(result3))
if (Utils.IsNotEmpty(result3))
{
return result3;
}
@@ -197,7 +197,7 @@ namespace ServiceLib.Handler
Uri uri = new(url);
//Authorization Header
if (!Utils.IsNullOrEmpty(uri.UserInfo))
if (Utils.IsNotEmpty(uri.UserInfo))
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Utils.Base64Encode(uri.UserInfo));
}

View File

@@ -16,12 +16,12 @@ namespace ServiceLib.Handler.Fmt
protected static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery)
{
if (!Utils.IsNullOrEmpty(item.flow))
if (Utils.IsNotEmpty(item.flow))
{
dicQuery.Add("flow", item.flow);
}
if (!Utils.IsNullOrEmpty(item.streamSecurity))
if (Utils.IsNotEmpty(item.streamSecurity))
{
dicQuery.Add("security", item.streamSecurity);
}
@@ -32,27 +32,27 @@ namespace ServiceLib.Handler.Fmt
dicQuery.Add("security", securityDef);
}
}
if (!Utils.IsNullOrEmpty(item.sni))
if (Utils.IsNotEmpty(item.sni))
{
dicQuery.Add("sni", item.sni);
}
if (!Utils.IsNullOrEmpty(item.alpn))
if (Utils.IsNotEmpty(item.alpn))
{
dicQuery.Add("alpn", Utils.UrlEncode(item.alpn));
}
if (!Utils.IsNullOrEmpty(item.fingerprint))
if (Utils.IsNotEmpty(item.fingerprint))
{
dicQuery.Add("fp", Utils.UrlEncode(item.fingerprint));
}
if (!Utils.IsNullOrEmpty(item.publicKey))
if (Utils.IsNotEmpty(item.publicKey))
{
dicQuery.Add("pbk", Utils.UrlEncode(item.publicKey));
}
if (!Utils.IsNullOrEmpty(item.shortId))
if (Utils.IsNotEmpty(item.shortId))
{
dicQuery.Add("sid", Utils.UrlEncode(item.shortId));
}
if (!Utils.IsNullOrEmpty(item.spiderX))
if (Utils.IsNotEmpty(item.spiderX))
{
dicQuery.Add("spx", Utils.UrlEncode(item.spiderX));
}
@@ -61,21 +61,21 @@ namespace ServiceLib.Handler.Fmt
dicQuery.Add("allowInsecure", "1");
}
dicQuery.Add("type", !Utils.IsNullOrEmpty(item.network) ? item.network : nameof(ETransport.tcp));
dicQuery.Add("type", Utils.IsNotEmpty(item.network) ? item.network : nameof(ETransport.tcp));
switch (item.network)
{
case nameof(ETransport.tcp):
dicQuery.Add("headerType", !Utils.IsNullOrEmpty(item.headerType) ? item.headerType : Global.None);
if (!Utils.IsNullOrEmpty(item.requestHost))
dicQuery.Add("headerType", Utils.IsNotEmpty(item.headerType) ? item.headerType : Global.None);
if (Utils.IsNotEmpty(item.requestHost))
{
dicQuery.Add("host", Utils.UrlEncode(item.requestHost));
}
break;
case nameof(ETransport.kcp):
dicQuery.Add("headerType", !Utils.IsNullOrEmpty(item.headerType) ? item.headerType : Global.None);
if (!Utils.IsNullOrEmpty(item.path))
dicQuery.Add("headerType", Utils.IsNotEmpty(item.headerType) ? item.headerType : Global.None);
if (Utils.IsNotEmpty(item.path))
{
dicQuery.Add("seed", Utils.UrlEncode(item.path));
}
@@ -84,11 +84,11 @@ namespace ServiceLib.Handler.Fmt
case nameof(ETransport.ws):
case nameof(ETransport.httpupgrade):
case nameof(ETransport.splithttp):
if (!Utils.IsNullOrEmpty(item.requestHost))
if (Utils.IsNotEmpty(item.requestHost))
{
dicQuery.Add("host", Utils.UrlEncode(item.requestHost));
}
if (!Utils.IsNullOrEmpty(item.path))
if (Utils.IsNotEmpty(item.path))
{
dicQuery.Add("path", Utils.UrlEncode(item.path));
}
@@ -97,24 +97,24 @@ namespace ServiceLib.Handler.Fmt
case nameof(ETransport.http):
case nameof(ETransport.h2):
dicQuery["type"] = nameof(ETransport.http);
if (!Utils.IsNullOrEmpty(item.requestHost))
if (Utils.IsNotEmpty(item.requestHost))
{
dicQuery.Add("host", Utils.UrlEncode(item.requestHost));
}
if (!Utils.IsNullOrEmpty(item.path))
if (Utils.IsNotEmpty(item.path))
{
dicQuery.Add("path", Utils.UrlEncode(item.path));
}
break;
case nameof(ETransport.quic):
dicQuery.Add("headerType", !Utils.IsNullOrEmpty(item.headerType) ? item.headerType : Global.None);
dicQuery.Add("headerType", Utils.IsNotEmpty(item.headerType) ? item.headerType : Global.None);
dicQuery.Add("quicSecurity", Utils.UrlEncode(item.requestHost));
dicQuery.Add("key", Utils.UrlEncode(item.path));
break;
case nameof(ETransport.grpc):
if (!Utils.IsNullOrEmpty(item.path))
if (Utils.IsNotEmpty(item.path))
{
dicQuery.Add("authority", Utils.UrlEncode(item.requestHost));
dicQuery.Add("serviceName", Utils.UrlEncode(item.path));

View File

@@ -10,12 +10,12 @@
{
EConfigType.VMess => VmessFmt.ToUri(item),
EConfigType.Shadowsocks => ShadowsocksFmt.ToUri(item),
EConfigType.Socks => SocksFmt.ToUri(item),
EConfigType.SOCKS => SocksFmt.ToUri(item),
EConfigType.Trojan => TrojanFmt.ToUri(item),
EConfigType.VLESS => VLESSFmt.ToUri(item),
EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item),
EConfigType.Tuic => TuicFmt.ToUri(item),
EConfigType.Wireguard => WireguardFmt.ToUri(item),
EConfigType.TUIC => TuicFmt.ToUri(item),
EConfigType.WireGuard => WireguardFmt.ToUri(item),
_ => null,
};
@@ -49,7 +49,7 @@
{
return ShadowsocksFmt.Resolve(str, out msg);
}
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Socks]))
else if (str.StartsWith(Global.ProtocolShares[EConfigType.SOCKS]))
{
return SocksFmt.Resolve(str, out msg);
}
@@ -65,11 +65,11 @@
{
return Hysteria2Fmt.Resolve(str, out msg);
}
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Tuic]))
else if (str.StartsWith(Global.ProtocolShares[EConfigType.TUIC]))
{
return TuicFmt.Resolve(str, out msg);
}
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Wireguard]))
else if (str.StartsWith(Global.ProtocolShares[EConfigType.WireGuard]))
{
return WireguardFmt.Resolve(str, out msg);
}

View File

@@ -31,20 +31,20 @@
string url = string.Empty;
string remark = string.Empty;
if (!Utils.IsNullOrEmpty(item.remarks))
if (Utils.IsNotEmpty(item.remarks))
{
remark = "#" + Utils.UrlEncode(item.remarks);
}
var dicQuery = new Dictionary<string, string>();
if (!Utils.IsNullOrEmpty(item.sni))
if (Utils.IsNotEmpty(item.sni))
{
dicQuery.Add("sni", item.sni);
}
if (!Utils.IsNullOrEmpty(item.alpn))
if (Utils.IsNotEmpty(item.alpn))
{
dicQuery.Add("alpn", Utils.UrlEncode(item.alpn));
}
if (!Utils.IsNullOrEmpty(item.path))
if (Utils.IsNotEmpty(item.path))
{
dicQuery.Add("obfs", "salamander");
dicQuery.Add("obfs-password", Utils.UrlEncode(item.path));

View File

@@ -30,7 +30,7 @@ namespace ServiceLib.Handler.Fmt
string url = string.Empty;
string remark = string.Empty;
if (!Utils.IsNullOrEmpty(item.remarks))
if (Utils.IsNotEmpty(item.remarks))
{
remark = "#" + Utils.UrlEncode(item.remarks);
}
@@ -59,7 +59,7 @@ namespace ServiceLib.Handler.Fmt
ProfileItem item = new();
var base64 = match.Groups["base64"].Value.TrimEnd('/');
var tag = match.Groups["tag"].Value;
if (!Utils.IsNullOrEmpty(tag))
if (Utils.IsNotEmpty(tag))
{
item.remarks = Utils.UrlDecode(tag);
}
@@ -128,7 +128,7 @@ namespace ServiceLib.Handler.Fmt
{
//obfs-host exists
var obfsHost = queryParameters["plugin"]?.Split(';').FirstOrDefault(t => t.Contains("obfs-host"));
if (queryParameters["plugin"].Contains("obfs=http") && !Utils.IsNullOrEmpty(obfsHost))
if (queryParameters["plugin"].Contains("obfs=http") && Utils.IsNotEmpty(obfsHost))
{
obfsHost = obfsHost?.Replace("obfs-host=", "");
item.network = Global.DefaultNetwork;

View File

@@ -17,7 +17,7 @@
return null;
}
item.configType = EConfigType.Socks;
item.configType = EConfigType.SOCKS;
return item;
}
@@ -28,7 +28,7 @@
string url = string.Empty;
string remark = string.Empty;
if (!Utils.IsNullOrEmpty(item.remarks))
if (Utils.IsNotEmpty(item.remarks))
{
remark = "#" + Utils.UrlEncode(item.remarks);
}
@@ -41,7 +41,7 @@
//new
var pw = Utils.Base64Encode($"{item.security}:{item.id}");
url = $"{pw}@{GetIpv6(item.address)}:{item.port}";
url = $"{Global.ProtocolShares[EConfigType.Socks]}{url}{remark}";
url = $"{Global.ProtocolShares[EConfigType.SOCKS]}{url}{remark}";
return url;
}
@@ -49,9 +49,9 @@
{
ProfileItem item = new()
{
configType = EConfigType.Socks
configType = EConfigType.SOCKS
};
result = result[Global.ProtocolShares[EConfigType.Socks].Length..];
result = result[Global.ProtocolShares[EConfigType.SOCKS].Length..];
//remark
int indexRemark = result.IndexOf("#");
if (indexRemark > 0)

View File

@@ -30,7 +30,7 @@
string url = string.Empty;
string remark = string.Empty;
if (!Utils.IsNullOrEmpty(item.remarks))
if (Utils.IsNotEmpty(item.remarks))
{
remark = "#" + Utils.UrlEncode(item.remarks);
}

View File

@@ -8,7 +8,7 @@
ProfileItem item = new()
{
configType = EConfigType.Tuic
configType = EConfigType.TUIC
};
Uri url = new(str);
@@ -36,16 +36,16 @@
string url = string.Empty;
string remark = string.Empty;
if (!Utils.IsNullOrEmpty(item.remarks))
if (Utils.IsNotEmpty(item.remarks))
{
remark = "#" + Utils.UrlEncode(item.remarks);
}
var dicQuery = new Dictionary<string, string>();
if (!Utils.IsNullOrEmpty(item.sni))
if (Utils.IsNotEmpty(item.sni))
{
dicQuery.Add("sni", item.sni);
}
if (!Utils.IsNullOrEmpty(item.alpn))
if (Utils.IsNotEmpty(item.alpn))
{
dicQuery.Add("alpn", Utils.UrlEncode(item.alpn));
}
@@ -57,7 +57,7 @@
$"{item.id}:{item.security}",
GetIpv6(item.address),
item.port);
url = $"{Global.ProtocolShares[EConfigType.Tuic]}{url}{query}{remark}";
url = $"{Global.ProtocolShares[EConfigType.TUIC]}{url}{query}{remark}";
return url;
}
}

View File

@@ -33,12 +33,12 @@
string url = string.Empty;
string remark = string.Empty;
if (!Utils.IsNullOrEmpty(item.remarks))
if (Utils.IsNotEmpty(item.remarks))
{
remark = "#" + Utils.UrlEncode(item.remarks);
}
var dicQuery = new Dictionary<string, string>();
if (!Utils.IsNullOrEmpty(item.security))
if (Utils.IsNotEmpty(item.security))
{
dicQuery.Add("encryption", item.security);
}

View File

@@ -78,12 +78,12 @@
item.alterId = Utils.ToInt(vmessQRCode.aid);
item.security = Utils.ToString(vmessQRCode.scy);
item.security = !Utils.IsNullOrEmpty(vmessQRCode.scy) ? vmessQRCode.scy : Global.DefaultSecurity;
if (!Utils.IsNullOrEmpty(vmessQRCode.net))
item.security = Utils.IsNotEmpty(vmessQRCode.scy) ? vmessQRCode.scy : Global.DefaultSecurity;
if (Utils.IsNotEmpty(vmessQRCode.net))
{
item.network = vmessQRCode.net;
}
if (!Utils.IsNullOrEmpty(vmessQRCode.type))
if (Utils.IsNotEmpty(vmessQRCode.type))
{
item.headerType = vmessQRCode.type;
}

View File

@@ -8,7 +8,7 @@
ProfileItem item = new()
{
configType = EConfigType.Wireguard
configType = EConfigType.WireGuard
};
Uri url = new(str);
@@ -34,25 +34,25 @@
string url = string.Empty;
string remark = string.Empty;
if (!Utils.IsNullOrEmpty(item.remarks))
if (Utils.IsNotEmpty(item.remarks))
{
remark = "#" + Utils.UrlEncode(item.remarks);
}
var dicQuery = new Dictionary<string, string>();
if (!Utils.IsNullOrEmpty(item.publicKey))
if (Utils.IsNotEmpty(item.publicKey))
{
dicQuery.Add("publickey", Utils.UrlEncode(item.publicKey));
}
if (!Utils.IsNullOrEmpty(item.path))
if (Utils.IsNotEmpty(item.path))
{
dicQuery.Add("reserved", Utils.UrlEncode(item.path));
}
if (!Utils.IsNullOrEmpty(item.requestHost))
if (Utils.IsNotEmpty(item.requestHost))
{
dicQuery.Add("address", Utils.UrlEncode(item.requestHost));
}
if (!Utils.IsNullOrEmpty(item.shortId))
if (Utils.IsNotEmpty(item.shortId))
{
dicQuery.Add("mtu", Utils.UrlEncode(item.shortId));
}
@@ -62,7 +62,7 @@
Utils.UrlEncode(item.id),
GetIpv6(item.address),
item.port);
url = $"{Global.ProtocolShares[EConfigType.Wireguard]}{url}/{query}{remark}";
url = $"{Global.ProtocolShares[EConfigType.WireGuard]}{url}/{query}{remark}";
return url;
}
}

View File

@@ -38,6 +38,14 @@
SQLiteHelper.Instance.CreateTable<RoutingItem>();
SQLiteHelper.Instance.CreateTable<ProfileExItem>();
SQLiteHelper.Instance.CreateTable<DNSItem>();
//TODO
//Prepare to remove the clash
SQLiteHelper.Instance.Execute($"update ProfileItem set coreType = 13 where coreType = 11");
SQLiteHelper.Instance.Execute($"update ProfileItem set coreType = 13 where coreType = 12");
//Prepare to remove the SagerNet
SQLiteHelper.Instance.Execute($"update ProfileItem set coreType = 2 where coreType = 3");
}
#region Config
@@ -104,11 +112,11 @@
from ProfileItem a
left join SubItem b on a.subid = b.id
where 1=1 ";
if (!Utils.IsNullOrEmpty(subid))
if (Utils.IsNotEmpty(subid))
{
sql += $" and a.subid = '{subid}'";
}
if (!Utils.IsNullOrEmpty(filter))
if (Utils.IsNotEmpty(filter))
{
if (filter.Contains('\''))
{
@@ -168,7 +176,7 @@
return SQLiteHelper.Instance.Table<ProfileItem>().FirstOrDefault(it => it.indexId == indexId);
}
public ProfileItem? GetProfileItemViaRemarks(string remarks)
public ProfileItem? GetProfileItemViaRemarks(string? remarks)
{
if (Utils.IsNullOrEmpty(remarks))
{

View File

@@ -35,7 +35,7 @@ namespace ServiceLib.Handler
private void IndexIdEnqueue(string indexId)
{
if (!Utils.IsNullOrEmpty(indexId) && !_queIndexIds.Contains(indexId))
if (Utils.IsNotEmpty(indexId) && !_queIndexIds.Contains(indexId))
{
_queIndexIds.Enqueue(indexId);
}

View File

@@ -88,7 +88,7 @@ namespace ServiceLib.Handler.Statistics
while (!res.CloseStatus.HasValue)
{
var result = Encoding.UTF8.GetString(buffer, 0, res.Count);
if (!Utils.IsNullOrEmpty(result))
if (Utils.IsNotEmpty(result))
{
ParseOutput(result, out ulong up, out ulong down);

View File

@@ -12,7 +12,7 @@
public void RegUpdateTask(Config config, Action<bool, string> update)
{
Task.Run(() => UpdateTaskRunSubscription(config, update));
Task.Run(() => UpdateTaskRunGeo(config, update));
//Task.Run(() => UpdateTaskRunGeo(config, update));
}
private async Task UpdateTaskRunSubscription(Config config, Action<bool, string> update)

View File

@@ -143,7 +143,7 @@ namespace ServiceLib.Handler
string url = item.url.TrimEx();
string userAgent = item.userAgent.TrimEx();
string hashCode = $"{item.remarks}->";
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || (!Utils.IsNullOrEmpty(subId) && item.id != subId))
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || (Utils.IsNotEmpty(subId) && item.id != subId))
{
//_updateFunc(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
continue;
@@ -169,7 +169,7 @@ namespace ServiceLib.Handler
//one url
url = Utils.GetPunycode(url);
//convert
if (!Utils.IsNullOrEmpty(item.convertTarget))
if (Utils.IsNotEmpty(item.convertTarget))
{
var subConvertUrl = Utils.IsNullOrEmpty(config.constItem.subConvertUrl) ? Global.SubConvertUrls.FirstOrDefault() : config.constItem.subConvertUrl;
url = string.Format(subConvertUrl!, Utils.UrlEncode(url));
@@ -189,9 +189,9 @@ namespace ServiceLib.Handler
}
//more url
if (Utils.IsNullOrEmpty(item.convertTarget) && !Utils.IsNullOrEmpty(item.moreUrl.TrimEx()))
if (Utils.IsNullOrEmpty(item.convertTarget) && Utils.IsNotEmpty(item.moreUrl.TrimEx()))
{
if (!Utils.IsNullOrEmpty(result) && Utils.IsBase64String(result!))
if (Utils.IsNotEmpty(result) && Utils.IsBase64String(result))
{
result = Utils.Base64Decode(result);
}
@@ -210,9 +210,9 @@ namespace ServiceLib.Handler
{
result2 = await downloadHandle.TryDownloadString(url2, false, userAgent);
}
if (!Utils.IsNullOrEmpty(result2))
if (Utils.IsNotEmpty(result2))
{
if (Utils.IsBase64String(result2!))
if (Utils.IsBase64String(result2))
{
result += Utils.Base64Decode(result2);
}
@@ -261,14 +261,10 @@ namespace ServiceLib.Handler
_updateFunc(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, "geo"));
}
public void RunAvailabilityCheck(Action<bool, string> update)
public async Task RunAvailabilityCheck(Action<bool, string> update)
{
Task.Run(async () =>
{
var time = await (new DownloadHandler()).RunAvailabilityCheck(null);
update(false, string.Format(ResUI.TestMeOutput, time));
});
var time = await (new DownloadHandler()).RunAvailabilityCheck(null);
update(false, string.Format(ResUI.TestMeOutput, time));
}
#region private
@@ -280,8 +276,8 @@ namespace ServiceLib.Handler
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
var url = coreInfo?.coreReleaseApiUrl;
var result = await downloadHandle.DownloadStringAsync(url, true, Global.AppName);
if (!Utils.IsNullOrEmpty(result))
var result = await downloadHandle.TryDownloadString(url, true, Global.AppName);
if (Utils.IsNotEmpty(result))
{
return await ParseDownloadUrl(type, result, preRelease);
}
@@ -372,7 +368,7 @@ namespace ServiceLib.Handler
{
var gitHubReleases = JsonUtils.Deserialize<List<GitHubRelease>>(gitHubReleaseApi);
var gitHubRelease = preRelease ? gitHubReleases?.First() : gitHubReleases?.First(r => r.Prerelease == false);
var version = new SemanticVersion(gitHubRelease?.TagName!);
var version = new SemanticVersion(gitHubRelease?.TagName);
var body = gitHubRelease?.Body;
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);

View File

@@ -94,7 +94,7 @@
public bool ignoreGeoUpdateCore { get; set; } = true;
public int autoUpdateInterval { get; set; } = 10;
public int autoUpdateInterval { get; set; }
public bool checkPreReleaseUpdate { get; set; } = false;

View File

@@ -105,6 +105,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Host filter 的本地化字符串。
/// </summary>
public static string ConnectionsHostFilterTitle {
get {
return ResourceManager.GetString("ConnectionsHostFilterTitle", resourceCulture);
}
}
/// <summary>
/// 查找类似 Note that custom configuration relies entirely on your own configuration and does not work with all settings. If you want to use the system proxy, please modify the listening port manually. 的本地化字符串。
/// </summary>
@@ -321,6 +330,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Invalid backup file 的本地化字符串。
/// </summary>
public static string LocalRestoreInvalidZipTips {
get {
return ResourceManager.GetString("LocalRestoreInvalidZipTips", resourceCulture);
}
}
/// <summary>
/// 查找类似 Address 的本地化字符串。
/// </summary>
@@ -637,7 +655,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [Http] server 的本地化字符串。
/// 查找类似 Add [HTTP] server 的本地化字符串。
/// </summary>
public static string menuAddHttpServer {
get {
@@ -682,7 +700,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [Socks] server 的本地化字符串。
/// 查找类似 Add [SOCKS] server 的本地化字符串。
/// </summary>
public static string menuAddSocksServer {
get {
@@ -700,7 +718,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [Tuic] server 的本地化字符串。
/// 查找类似 Add [TUIC] server 的本地化字符串。
/// </summary>
public static string menuAddTuicServer {
get {
@@ -727,7 +745,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [Wireguard] server 的本地化字符串。
/// 查找类似 Add [WireGuard] server 的本地化字符串。
/// </summary>
public static string menuAddWireguardServer {
get {

View File

@@ -536,7 +536,7 @@
<value>Add [Shadowsocks] server</value>
</data>
<data name="menuAddSocksServer" xml:space="preserve">
<value>Add [Socks] server</value>
<value>Add [SOCKS] server</value>
</data>
<data name="menuAddTrojanServer" xml:space="preserve">
<value>Add [Trojan] server</value>
@@ -1094,7 +1094,7 @@
<value>Use System Hosts</value>
</data>
<data name="menuAddTuicServer" xml:space="preserve">
<value>Add [Tuic] server</value>
<value>Add [TUIC] server</value>
</data>
<data name="TbHeaderType8" xml:space="preserve">
<value>Congestion control</value>
@@ -1115,7 +1115,7 @@
<value>Enable IPv6 Address</value>
</data>
<data name="menuAddWireguardServer" xml:space="preserve">
<value>Add [Wireguard] server</value>
<value>Add [WireGuard] server</value>
</data>
<data name="TbPrivateKey" xml:space="preserve">
<value>PrivateKey</value>
@@ -1148,7 +1148,7 @@
<value>*grpc Authority</value>
</data>
<data name="menuAddHttpServer" xml:space="preserve">
<value>Add [Http] server</value>
<value>Add [HTTP] server</value>
</data>
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
<value>Use Xray and enable non-Tun mode, which conflicts with the group previous proxy</value>
@@ -1315,4 +1315,10 @@
<data name="LvWebDavDirName" xml:space="preserve">
<value>Remote folder name (optional)</value>
</data>
<data name="LocalRestoreInvalidZipTips" xml:space="preserve">
<value>Invalid backup file</value>
</data>
<data name="ConnectionsHostFilterTitle" xml:space="preserve">
<value>Host filter</value>
</data>
</root>

View File

@@ -536,7 +536,7 @@
<value>Добавить сервер [Shadowsocks]</value>
</data>
<data name="menuAddSocksServer" xml:space="preserve">
<value>Добавить сервер [Socks]</value>
<value>Добавить сервер [SOCKS]</value>
</data>
<data name="menuAddTrojanServer" xml:space="preserve">
<value>Добавить сервер [Trojan]</value>

View File

@@ -536,7 +536,7 @@
<value>添加[Shadowsocks]服务器</value>
</data>
<data name="menuAddSocksServer" xml:space="preserve">
<value>添加[Socks]服务器</value>
<value>添加[SOCKS]服务器</value>
</data>
<data name="menuAddTrojanServer" xml:space="preserve">
<value>添加[Trojan]服务器</value>
@@ -1091,7 +1091,7 @@
<value>使用系统hosts</value>
</data>
<data name="menuAddTuicServer" xml:space="preserve">
<value>添加[Tuic]服务器</value>
<value>添加[TUIC]服务器</value>
</data>
<data name="TbHeaderType8" xml:space="preserve">
<value>拥塞控制算法</value>
@@ -1112,7 +1112,7 @@
<value>启用IPv6</value>
</data>
<data name="menuAddWireguardServer" xml:space="preserve">
<value>添加[Wireguard]服务器</value>
<value>添加[WireGuard]服务器</value>
</data>
<data name="TbPrivateKey" xml:space="preserve">
<value>PrivateKey</value>
@@ -1145,7 +1145,7 @@
<value>*grpc Authority</value>
</data>
<data name="menuAddHttpServer" xml:space="preserve">
<value>添加[Http]服务器</value>
<value>添加[HTTP]服务器</value>
</data>
<data name="TbSettingsEnableFragment" xml:space="preserve">
<value>启用分片Fragment</value>
@@ -1312,4 +1312,10 @@
<data name="LvWebDavDirName" xml:space="preserve">
<value>远程文件夹名称(可选)</value>
</data>
<data name="LocalRestoreInvalidZipTips" xml:space="preserve">
<value>无效备份文件</value>
</data>
<data name="ConnectionsHostFilterTitle" xml:space="preserve">
<value>主机过滤器</value>
</data>
</root>

View File

@@ -535,7 +535,7 @@
<value>新增[Shadowsocks]伺服器</value>
</data>
<data name="menuAddSocksServer" xml:space="preserve">
<value>新增[Socks]伺服器</value>
<value>新增[SOCKS]伺服器</value>
</data>
<data name="menuAddTrojanServer" xml:space="preserve">
<value>新增[Trojan]伺服器</value>
@@ -1082,7 +1082,7 @@
<value>IP 或 IP CIDR</value>
</data>
<data name="menuAddTuicServer" xml:space="preserve">
<value>新增[Tuic]伺服器</value>
<value>新增[TUIC]伺服器</value>
</data>
<data name="LvPrevProfile" xml:space="preserve">
<value>前置代理別名</value>
@@ -1118,7 +1118,7 @@
<value>*grpc Authority</value>
</data>
<data name="menuAddHttpServer" xml:space="preserve">
<value>新增[Http]伺服器</value>
<value>新增[HTTP]伺服器</value>
</data>
<data name="TbSettingsEnableFragment" xml:space="preserve">
<value>啟用分片Fragment</value>
@@ -1192,4 +1192,10 @@
<data name="LvWebDavDirName" xml:space="preserve">
<value>遠端資料夾名稱(可選)</value>
</data>
<data name="LocalRestoreInvalidZipTips" xml:space="preserve">
<value>無效備份文件</value>
</data>
<data name="ConnectionsHostFilterTitle" xml:space="preserve">
<value>主機過濾器</value>
</data>
</root>

View File

@@ -4,17 +4,17 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>6.58</Version>
<Version>6.60.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Downloader" Version="3.1.2" />
<PackageReference Include="ReactiveUI" Version="20.1.1" />
<PackageReference Include="Downloader" Version="3.2.0" />
<PackageReference Include="ReactiveUI" Version="20.1.63" />
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
<PackageReference Include="Splat.NLog" Version="15.1.1" />
<PackageReference Include="Splat.NLog" Version="15.2.22" />
<PackageReference Include="WebDav.Client" Version="2.8.0" />
<PackageReference Include="YamlDotNet" Version="16.1.0" />
<PackageReference Include="YamlDotNet" Version="16.1.2" />
<PackageReference Include="QRCoder" Version="1.6.0" />
</ItemGroup>

View File

@@ -90,7 +90,7 @@ namespace ServiceLib.ViewModels
if (ConfigHandler.AddCustomServer(_config, item, false) == 0)
{
_noticeHandler?.Enqueue(ResUI.SuccessfullyImportedCustomServer);
if (!Utils.IsNullOrEmpty(item.indexId))
if (Utils.IsNotEmpty(item.indexId))
{
SelectedSource = JsonUtils.DeepCopy(item);
}

View File

@@ -21,7 +21,7 @@ namespace ServiceLib.ViewModels
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
_updateView = updateView;
if (profileItem.id.IsNullOrEmpty())
if (profileItem.indexId.IsNullOrEmpty())
{
profileItem.network = Global.DefaultNetwork;
profileItem.headerType = Global.None;
@@ -74,8 +74,8 @@ namespace ServiceLib.ViewModels
return;
}
}
if (SelectedSource.configType != EConfigType.Socks
&& SelectedSource.configType != EConfigType.Http)
if (SelectedSource.configType != EConfigType.SOCKS
&& SelectedSource.configType != EConfigType.HTTP)
{
if (Utils.IsNullOrEmpty(SelectedSource.id))
{

View File

@@ -7,6 +7,9 @@ namespace ServiceLib.ViewModels
{
public class BackupAndRestoreViewModel : MyReactiveObject
{
private readonly string _guiConfigs = "guiConfigs";
private static string BackupFileName => $"backup_{DateTime.Now:yyyyMMddHHmmss}.zip";
public ReactiveCommand<Unit, Unit> RemoteBackupCmd { get; }
public ReactiveCommand<Unit, Unit> RemoteRestoreCmd { get; }
public ReactiveCommand<Unit, Unit> WebDavCheckCmd { get; }
@@ -65,7 +68,7 @@ namespace ServiceLib.ViewModels
private async Task RemoteBackup()
{
DisplayOperationMsg();
var fileName = Utils.GetBackupPath($"backup_{DateTime.Now:yyyyMMddHHmmss}.zip");
var fileName = Utils.GetBackupPath(BackupFileName);
var result = await CreateZipFileFromDirectory(fileName);
if (result)
{
@@ -122,9 +125,16 @@ namespace ServiceLib.ViewModels
{
return;
}
//check
var lstFiles = FileManager.GetFilesFromZip(fileName);
if (lstFiles is null || !lstFiles.Where(t => t.Contains(_guiConfigs)).Any())
{
DisplayOperationMsg(ResUI.LocalRestoreInvalidZipTips);
return;
}
//backup first
var fileBackup = Utils.GetBackupPath($"backup_{DateTime.Now:yyyyMMddHHmmss}.zip");
var fileBackup = Utils.GetBackupPath(BackupFileName);
var result = await CreateZipFileFromDirectory(fileBackup);
if (result)
{
@@ -145,9 +155,9 @@ namespace ServiceLib.ViewModels
var configDir = Utils.GetConfigPath();
var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}");
var configDirTemp = Path.Combine(configDirZipTemp, "guiConfigs");
var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs);
await Task.Run(() => FileManager.CopyDirectory(configDir, configDirTemp, true, "cache.db"));
await Task.Run(() => FileManager.CopyDirectory(configDir, configDirTemp, false, "cache.db"));
var ret = await Task.Run(() => FileManager.CreateFromDirectory(configDirZipTemp, fileName));
await Task.Run(() => Directory.Delete(configDirZipTemp, true));
return ret;

View File

@@ -19,6 +19,9 @@ namespace ServiceLib.ViewModels
public ReactiveCommand<Unit, Unit> ConnectionCloseCmd { get; }
public ReactiveCommand<Unit, Unit> ConnectionCloseAllCmd { get; }
[Reactive]
public string HostFilter { get; set; }
[Reactive]
public int SortingSelected { get; set; }
@@ -34,7 +37,7 @@ namespace ServiceLib.ViewModels
var canEditRemove = this.WhenAnyValue(
x => x.SelectedSource,
selectedSource => selectedSource != null && !string.IsNullOrEmpty(selectedSource.id));
selectedSource => selectedSource != null && Utils.IsNotEmpty(selectedSource.id));
this.WhenAnyValue(
x => x.SortingSelected,
@@ -77,7 +80,7 @@ namespace ServiceLib.ViewModels
{
var lastTime = DateTime.Now;
Observable.Interval(TimeSpan.FromSeconds(10))
Observable.Interval(TimeSpan.FromSeconds(5))
.Subscribe(x =>
{
if (!(AutoRefresh && _config.uiItem.showInTaskbar && _config.IsRunningCore(ECoreType.clash)))
@@ -118,12 +121,18 @@ namespace ServiceLib.ViewModels
var lstModel = new List<ClashConnectionModel>();
foreach (var item in connections ?? [])
{
var host = $"{(Utils.IsNullOrEmpty(item.metadata.host) ? item.metadata.destinationIP : item.metadata.host)}:{item.metadata.destinationPort}";
if (HostFilter.IsNotEmpty() && !host.Contains(HostFilter))
{
continue;
}
ClashConnectionModel model = new();
model.id = item.id;
model.network = item.metadata.network;
model.type = item.metadata.type;
model.host = $"{(string.IsNullOrEmpty(item.metadata.host) ? item.metadata.destinationIP : item.metadata.host)}:{item.metadata.destinationPort}";
model.host = host;
var sp = (dtNow - item.start);
model.time = sp.TotalSeconds < 0 ? 1 : sp.TotalSeconds;
model.upload = item.upload;

View File

@@ -57,7 +57,7 @@ namespace ServiceLib.ViewModels
this.WhenAnyValue(
x => x.SelectedGroup,
y => y != null && !string.IsNullOrEmpty(y.name))
y => y != null && Utils.IsNotEmpty(y.name))
.Subscribe(c => RefreshProxyDetails(c));
this.WhenAnyValue(
@@ -194,7 +194,7 @@ namespace ServiceLib.ViewModels
{
foreach (var it in proxyGroups)
{
if (string.IsNullOrEmpty(it.name) || !_proxies.ContainsKey(it.name))
if (Utils.IsNullOrEmpty(it.name) || !_proxies.ContainsKey(it.name))
{
continue;
}
@@ -220,7 +220,7 @@ namespace ServiceLib.ViewModels
continue;
}
var item = _proxyGroups.Where(t => t.name == kv.Key).FirstOrDefault();
if (item != null && !string.IsNullOrEmpty(item.name))
if (item != null && Utils.IsNotEmpty(item.name))
{
continue;
}
@@ -257,7 +257,7 @@ namespace ServiceLib.ViewModels
return;
}
var name = SelectedGroup?.name;
if (string.IsNullOrEmpty(name))
if (Utils.IsNullOrEmpty(name))
{
return;
}
@@ -342,21 +342,21 @@ namespace ServiceLib.ViewModels
public void SetActiveProxy()
{
if (SelectedGroup == null || string.IsNullOrEmpty(SelectedGroup.name))
if (SelectedGroup == null || Utils.IsNullOrEmpty(SelectedGroup.name))
{
return;
}
if (SelectedDetail == null || string.IsNullOrEmpty(SelectedDetail.name))
if (SelectedDetail == null || Utils.IsNullOrEmpty(SelectedDetail.name))
{
return;
}
var name = SelectedGroup.name;
if (string.IsNullOrEmpty(name))
if (Utils.IsNullOrEmpty(name))
{
return;
}
var nameNode = SelectedDetail.name;
if (string.IsNullOrEmpty(nameNode))
if (Utils.IsNullOrEmpty(nameNode))
{
return;
}
@@ -393,7 +393,7 @@ namespace ServiceLib.ViewModels
GetClashProxies(true);
return;
}
if (string.IsNullOrEmpty(result))
if (Utils.IsNullOrEmpty(result))
{
return;
}

View File

@@ -58,7 +58,7 @@ namespace ServiceLib.ViewModels
private async Task SaveSettingAsync()
{
if (!Utils.IsNullOrEmpty(normalDNS))
if (Utils.IsNotEmpty(normalDNS))
{
var obj = JsonUtils.ParseJson(normalDNS);
if (obj != null && obj["servers"] != null)
@@ -73,7 +73,7 @@ namespace ServiceLib.ViewModels
}
}
}
if (!Utils.IsNullOrEmpty(normalDNS2))
if (Utils.IsNotEmpty(normalDNS2))
{
var obj2 = JsonUtils.Deserialize<Dns4Sbox>(normalDNS2);
if (obj2 == null)
@@ -82,7 +82,7 @@ namespace ServiceLib.ViewModels
return;
}
}
if (!Utils.IsNullOrEmpty(tunDNS2))
if (Utils.IsNotEmpty(tunDNS2))
{
var obj2 = JsonUtils.Deserialize<Dns4Sbox>(tunDNS2);
if (obj2 == null)

View File

@@ -14,6 +14,7 @@ namespace ServiceLib.ViewModels
#region private prop
private CoreHandler _coreHandler;
private bool _isAdministrator { get; set; }
#endregion private prop
@@ -139,17 +140,16 @@ namespace ServiceLib.ViewModels
[Reactive]
public int TabMainSelectedIndex { get; set; }
public bool IsAdministrator { get; set; }
#endregion UI
#region Init
public MainWindowViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
public MainWindowViewModel(bool isAdministrator, Func<EViewAction, object?, Task<bool>>? updateView)
{
_config = LazyConfig.Instance.Config;
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
_updateView = updateView;
_isAdministrator = isAdministrator;
MessageBus.Current.Listen<string>(Global.CommandRefreshProfiles).Subscribe(async x => await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null));
@@ -158,6 +158,16 @@ namespace ServiceLib.ViewModels
Init();
_config.uiItem.showInTaskbar = true;
if (_config.tunModeItem.enableTun && _isAdministrator)
{
EnableTun = true;
}
else
{
_config.tunModeItem.enableTun = EnableTun = false;
}
#region WhenAnyValue && ReactiveCommand
this.WhenAnyValue(
@@ -196,11 +206,11 @@ namespace ServiceLib.ViewModels
});
AddSocksServerCmd = ReactiveCommand.Create(() =>
{
AddServerAsync(true, EConfigType.Socks);
AddServerAsync(true, EConfigType.SOCKS);
});
AddHttpServerCmd = ReactiveCommand.Create(() =>
{
AddServerAsync(true, EConfigType.Http);
AddServerAsync(true, EConfigType.HTTP);
});
AddTrojanServerCmd = ReactiveCommand.Create(() =>
{
@@ -212,11 +222,11 @@ namespace ServiceLib.ViewModels
});
AddTuicServerCmd = ReactiveCommand.Create(() =>
{
AddServerAsync(true, EConfigType.Tuic);
AddServerAsync(true, EConfigType.TUIC);
});
AddWireguardServerCmd = ReactiveCommand.Create(() =>
{
AddServerAsync(true, EConfigType.Wireguard);
AddServerAsync(true, EConfigType.WireGuard);
});
AddCustomServerCmd = ReactiveCommand.Create(() =>
{
@@ -319,8 +329,6 @@ namespace ServiceLib.ViewModels
#endregion WhenAnyValue && ReactiveCommand
AutoHideStartup();
_config.uiItem.showInTaskbar = true;
}
private void Init()
@@ -349,10 +357,6 @@ namespace ServiceLib.ViewModels
private void UpdateHandler(bool notify, string msg)
{
if (!_config.uiItem.showInTaskbar)
{
return;
}
_noticeHandler?.SendMessage(msg);
if (notify)
{
@@ -611,21 +615,16 @@ namespace ServiceLib.ViewModels
SetDefaultServer(SelectedServer.ID);
}
public void TestServerAvailability()
public async Task TestServerAvailability()
{
var item = ConfigHandler.GetDefaultServer(_config);
if (item == null)
{
return;
}
(new UpdateHandler()).RunAvailabilityCheck(async (bool success, string msg) =>
await (new UpdateHandler()).RunAvailabilityCheck(async (bool success, string msg) =>
{
_noticeHandler?.SendMessageEx(msg);
if (!_config.uiItem.showInTaskbar)
{
return;
}
await _updateView?.Invoke(EViewAction.DispatcherServerAvailability, msg);
});
}
@@ -715,7 +714,7 @@ namespace ServiceLib.ViewModels
LoadCore().ContinueWith(async task =>
{
TestServerAvailability();
await TestServerAvailability();
await _updateView?.Invoke(EViewAction.DispatcherReload, null);
});
@@ -776,7 +775,8 @@ namespace ServiceLib.ViewModels
private async Task ChangeSystemProxyStatusAsync(ESysProxyType type, bool blChange)
{
await _updateView?.Invoke(EViewAction.UpdateSysProxy, _config.tunModeItem.enableTun ? true : false);
//await _updateView?.Invoke(EViewAction.UpdateSysProxy, _config.tunModeItem.enableTun ? true : false);
await _updateView?.Invoke(EViewAction.UpdateSysProxy, false);
_noticeHandler?.SendMessageEx($"{ResUI.TipChangeSystemProxy} - {_config.systemProxyItem.sysProxyType.ToString()}");
BlSystemProxyClear = (type == ESysProxyType.ForcedClear);
@@ -862,12 +862,13 @@ namespace ServiceLib.ViewModels
{
_config.tunModeItem.enableTun = EnableTun;
// When running as a non-administrator, reboot to administrator mode
if (EnableTun && !IsAdministrator)
if (EnableTun && !_isAdministrator)
{
_config.tunModeItem.enableTun = false;
RebootAsAdmin();
return;
}
ConfigHandler.SaveConfig(_config);
Reload();
}
}

View File

@@ -60,6 +60,10 @@ namespace ServiceLib.ViewModels
}
_blLockShow = true;
if (!_config.uiItem.showInTaskbar)
{
await Task.Delay(1000);
}
await Task.Delay(100);
var txt = string.Join("", _queueMsg.ToArray());
@@ -72,7 +76,7 @@ namespace ServiceLib.ViewModels
{
//filter msg
if (MsgFilter != _lastMsgFilter) _lastMsgFilterNotAvailable = false;
if (!Utils.IsNullOrEmpty(MsgFilter) && !_lastMsgFilterNotAvailable)
if (Utils.IsNotEmpty(MsgFilter) && !_lastMsgFilterNotAvailable)
{
try
{

View File

@@ -265,13 +265,13 @@ namespace ServiceLib.ViewModels
var item = _profileItems.Where(it => it.indexId == result.IndexId).FirstOrDefault();
if (item != null)
{
if (!Utils.IsNullOrEmpty(result.Delay))
if (Utils.IsNotEmpty(result.Delay))
{
int.TryParse(result.Delay, out int temp);
item.delay = temp;
item.delayVal = $"{result.Delay} {Global.DelayUnit}";
}
if (!Utils.IsNullOrEmpty(result.Speed))
if (Utils.IsNotEmpty(result.Speed))
{
item.speedVal = $"{result.Speed} {Global.SpeedUnit}";
}

View File

@@ -80,7 +80,7 @@ namespace ServiceLib.ViewModels
|| SelectedSource.ip?.Count > 0
|| SelectedSource.protocol?.Count > 0
|| SelectedSource.process?.Count > 0
|| !Utils.IsNullOrEmpty(SelectedSource.port);
|| Utils.IsNotEmpty(SelectedSource.port);
if (!hasRule)
{

View File

@@ -13,7 +13,10 @@
<TrayIcon.Icons>
<TrayIcons>
<TrayIcon Clicked="TrayIcon_Clicked" Icon="/Assets/NotifyIcon1.ico">
<TrayIcon
Clicked="TrayIcon_Clicked"
Icon="/Assets/NotifyIcon1.ico"
ToolTipText="v2rayN Desktop">
<TrayIcon.Menu>
<NativeMenu>
<NativeMenuItem Click="MenuAddServerViaClipboardClick" Header="{x:Static resx:ResUI.menuAddServerViaClipboard}" />

View File

@@ -5,22 +5,6 @@
</Border>
</Design.PreviewWith>
<Style Selector="TextBlock.Margin4">
<Setter Property="Margin" Value="8" />
</Style>
<Style Selector="StackPanel.Margin4">
<Setter Property="Margin" Value="8" />
</Style>
<Style Selector="DockPanel.Margin4">
<Setter Property="Margin" Value="8" />
</Style>
<Style Selector="WrapPanel.Margin4">
<Setter Property="Margin" Value="8" />
</Style>
<Style Selector="Grid.Margin4">
<Setter Property="Margin" Value="8" />
</Style>
<Style Selector="TextBlock.Margin8">
<Setter Property="Margin" Value="8" />
</Style>

View File

@@ -70,7 +70,7 @@ namespace v2rayN.Desktop.ViewModels
y => y != null && !y.IsNullOrEmpty())
.Subscribe(c =>
{
if (!Utils.IsNullOrEmpty(CurrentLanguage) && _config.uiItem.currentLanguage != CurrentLanguage)
if (Utils.IsNotEmpty(CurrentLanguage) && _config.uiItem.currentLanguage != CurrentLanguage)
{
_config.uiItem.currentLanguage = CurrentLanguage;
Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage);

View File

@@ -16,7 +16,7 @@
<DockPanel Classes="Margin8">
<StackPanel
HorizontalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
<Button
@@ -57,14 +57,14 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.menuServers}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbRemarks}" />
<TextBox
@@ -74,13 +74,13 @@
Width="400"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Classes="Margin4" />
Classes="Margin8" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbAddress}" />
<TextBox
x:Name="txtAddress"
@@ -89,7 +89,7 @@
Width="400"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
IsReadOnly="True" />
<StackPanel
Grid.Row="2"
@@ -110,7 +110,7 @@
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbCoreType}" />
<ComboBox
x:Name="cmbCoreType"
@@ -118,24 +118,24 @@
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
Classes="Margin4"
Classes="Margin8"
MaxDropDownHeight="1000" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbDisplayLog}" />
<StackPanel
Grid.Row="4"
Grid.Column="1"
Classes="Margin4"
Classes="Margin8"
Orientation="Horizontal">
<ToggleSwitch
x:Name="togDisplayLog"
HorizontalAlignment="Left"
Classes="Margin4" />
Classes="Margin8" />
<TextBlock
Margin="8,0"
VerticalAlignment="Center"
@@ -146,7 +146,7 @@
Grid.Row="5"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbPreSocksPort}" />
<TextBox
x:Name="txtPreSocksPort"
@@ -154,12 +154,12 @@
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
Classes="Margin4" />
Classes="Margin8" />
<StackPanel
Grid.Row="6"
Grid.Column="1"
Grid.ColumnSpan="2"
Classes="Margin4">
Classes="Margin8">
<TextBlock
Width="500"
VerticalAlignment="Center"

File diff suppressed because it is too large Load Diff

View File

@@ -85,8 +85,8 @@ namespace v2rayN.Desktop.Views
});
break;
case EConfigType.Socks:
case EConfigType.Http:
case EConfigType.SOCKS:
case EConfigType.HTTP:
gridSocks.IsVisible = true;
break;
@@ -121,7 +121,7 @@ namespace v2rayN.Desktop.Views
cmbFingerprint.SelectedValue = string.Empty;
break;
case EConfigType.Tuic:
case EConfigType.TUIC:
gridTuic.IsVisible = true;
sepa2.IsVisible = false;
gridTransport.IsVisible = false;
@@ -135,7 +135,7 @@ namespace v2rayN.Desktop.Views
});
break;
case EConfigType.Wireguard:
case EConfigType.WireGuard:
gridWireguard.IsVisible = true;
sepa2.IsVisible = false;
@@ -168,8 +168,8 @@ namespace v2rayN.Desktop.Views
this.Bind(ViewModel, vm => vm.SelectedSource.security, v => v.cmbSecurity3.SelectedValue).DisposeWith(disposables);
break;
case EConfigType.Socks:
case EConfigType.Http:
case EConfigType.SOCKS:
case EConfigType.HTTP:
this.Bind(ViewModel, vm => vm.SelectedSource.id, v => v.txtId4.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.security, v => v.txtSecurity4.Text).DisposeWith(disposables);
break;
@@ -190,13 +190,13 @@ namespace v2rayN.Desktop.Views
this.Bind(ViewModel, vm => vm.SelectedSource.path, v => v.txtPath7.Text).DisposeWith(disposables);
break;
case EConfigType.Tuic:
case EConfigType.TUIC:
this.Bind(ViewModel, vm => vm.SelectedSource.id, v => v.txtId8.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.security, v => v.txtSecurity8.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.headerType, v => v.cmbHeaderType8.SelectedValue).DisposeWith(disposables);
break;
case EConfigType.Wireguard:
case EConfigType.WireGuard:
this.Bind(ViewModel, vm => vm.SelectedSource.id, v => v.txtId9.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.publicKey, v => v.txtPublicKey9.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.path, v => v.txtPath9.Text).DisposeWith(disposables);

View File

@@ -18,6 +18,13 @@
DockPanel.Dock="Top"
Orientation="Horizontal">
<TextBox
x:Name="txtHostFilter"
Width="200"
Margin="8,0"
VerticalContentAlignment="Center"
Watermark="{x:Static resx:ResUI.ConnectionsHostFilterTitle}" />
<TextBlock
Margin="8,0"
VerticalAlignment="Center"

View File

@@ -21,6 +21,7 @@ namespace v2rayN.Desktop.Views
this.BindCommand(ViewModel, vm => vm.ConnectionCloseCmd, v => v.menuConnectionClose).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.SortingSelected, v => v.cmbSorting.SelectedIndex).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);

View File

@@ -92,7 +92,6 @@
<DockPanel>
<ListBox
x:Name="lstProxyGroups"
Margin="0,0,5,0"
DockPanel.Dock="Left"
ItemsSource="{Binding ProxyGroups}">
<ItemsControl.ItemsPanel>
@@ -108,16 +107,17 @@
Padding="0"
Theme="{StaticResource CardBorder}">
<DockPanel>
<Grid Grid.Column="0" Classes="Margin4">
<Grid Grid.Column="0" Classes="Margin8">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition Height="1*" />
<RowDefinition Height="8" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<TextBlock DockPanel.Dock="Right" Text="{Binding type}" />
<TextBlock Text="{Binding name}" />
</DockPanel>
<TextBlock Grid.Row="1" Text="{Binding now}" />
<TextBlock Grid.Row="2" Text="{Binding now}" />
</Grid>
</DockPanel>
</Border>
@@ -141,6 +141,7 @@
<DataTemplate>
<Border
Width="160"
Margin="0"
Padding="0"
Theme="{StaticResource CardBorder}">
<DockPanel>
@@ -152,16 +153,17 @@
CornerRadius="4"
DockPanel.Dock="Left"
IsVisible="{Binding isActive}" />
<Grid Classes="Margin4">
<Grid Classes="Margin8">
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="1*" />
<RowDefinition Height="8" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
Text="{Binding name}"
TextWrapping="WrapWithOverflow" />
<DockPanel Grid.Row="1">
<DockPanel Grid.Row="2">
<TextBlock
DockPanel.Dock="Right"
Foreground="{Binding Path=delay, Converter={StaticResource DelayColorConverter}}"

View File

@@ -16,7 +16,7 @@
<DockPanel Classes="Margin8">
<StackPanel
HorizontalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
<Button
@@ -43,9 +43,9 @@
Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" />
<TextBlock VerticalAlignment="Center" Classes="Margin8">
<Button Click="linkDnsObjectDoc_Click">
<HyperlinkButton Classes="WithIcon" Click="linkDnsObjectDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" />
</Button>
</HyperlinkButton>
</TextBlock>
<Button
x:Name="btnImportDefConfig4V2ray"
@@ -95,7 +95,7 @@
BorderThickness="1"
Classes="TextArea Margin8"
TextWrapping="Wrap"
ToolTip.Tip="Http/Socks" />
Watermark="HTTP/SOCKS" />
</DockPanel>
</TabItem>
@@ -103,9 +103,9 @@
<DockPanel Classes="Margin8">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Classes="Margin8">
<Button Click="linkDnsSingboxObjectDoc_Click">
<HyperlinkButton Classes="WithIcon" Click="linkDnsSingboxObjectDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" />
</Button>
</HyperlinkButton>
</TextBlock>
<Button
x:Name="btnImportDefConfig4Singbox"
@@ -153,7 +153,7 @@
BorderThickness="1"
Classes="TextArea Margin8"
TextWrapping="Wrap"
ToolTip.Tip="Http/Socks" />
Watermark="HTTP/SOCKS" />
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
@@ -165,7 +165,7 @@
BorderThickness="1"
Classes="TextArea Margin8"
TextWrapping="Wrap"
ToolTip.Tip="{x:Static resx:ResUI.TbSettingsTunMode}" />
Watermark="{x:Static resx:ResUI.TbSettingsTunMode}" />
</Grid>
</DockPanel>
</TabItem>

View File

@@ -15,7 +15,7 @@
mc:Ignorable="d">
<DockPanel Classes="Margin8">
<StackPanel
Classes="Margin4"
Classes="Margin8"
HorizontalAlignment="Center"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
@@ -60,13 +60,13 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbGlobalHotkeySetting}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbDisplayGUI}" />
@@ -74,68 +74,68 @@
x:Name="txtGlobalHotkey0"
Grid.Row="1"
Grid.Column="1"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
IsReadOnly="True" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbClearSystemProxy}" />
<TextBox
x:Name="txtGlobalHotkey1"
Grid.Row="2"
Grid.Column="1"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
IsReadOnly="True" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSetSystemProxy}" />
<TextBox
x:Name="txtGlobalHotkey2"
Grid.Row="3"
Grid.Column="1"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
IsReadOnly="True" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbNotChangeSystemProxy}" />
<TextBox
x:Name="txtGlobalHotkey3"
Grid.Row="4"
Grid.Column="1"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
IsReadOnly="True" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSystemProxyPac}" />
<TextBox
x:Name="txtGlobalHotkey4"
Grid.Row="5"
Grid.Column="1"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
IsReadOnly="True" />
</Grid>
<TextBlock
Grid.Row="1"
Classes="Margin4"
Classes="Margin8"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbGlobalHotkeySettingTip}" />
</Grid>

View File

@@ -148,7 +148,8 @@
<ToggleSwitch
x:Name="togEnableTun"
HorizontalAlignment="Left"
Classes="Margin4" />
Classes="Margin8"
Theme="{StaticResource SimpleToggleSwitch}" />
</StackPanel>
<StackPanel

View File

@@ -34,8 +34,9 @@ namespace v2rayN.Desktop.Views
menuPromotion.Click += menuPromotion_Click;
menuClose.Click += menuClose_Click;
var IsAdministrator = true;//WindowsUtils.IsAdministrator();
MessageBus.Current.Listen<string>(Global.CommandSendSnackMsg).Subscribe(x => DelegateSnackMsg(x));
ViewModel = new MainWindowViewModel(UpdateViewHandler);
ViewModel = new MainWindowViewModel(IsAdministrator, UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
//WindowsHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null);
@@ -114,24 +115,10 @@ namespace v2rayN.Desktop.Views
if (Utils.IsWindows())
{
var IsAdministrator = false;//WindowsUtils.IsAdministrator();
ViewModel.IsAdministrator = IsAdministrator;
this.Title = $"{Utils.GetVersion()} - {(IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
if (_config.tunModeItem.enableTun)
{
if (IsAdministrator)
{
ViewModel.EnableTun = true;
}
else
{
_config.tunModeItem.enableTun = ViewModel.EnableTun = false;
}
}
}
else
{
ViewModel.IsAdministrator = true;
this.Title = $"{Utils.GetVersion()}";
menuRebootAsAdmin.IsVisible = false;
menuSettingsSetUWP.IsVisible = false;

View File

@@ -20,7 +20,7 @@
Width="200"
Margin="8,0"
VerticalContentAlignment="Center"
ToolTip.Tip="{x:Static resx:ResUI.MsgFilterTitle}" />
Watermark="{x:Static resx:ResUI.MsgFilterTitle}" />
<Button
x:Name="btnCopy"
@@ -62,7 +62,8 @@
x:Name="togAutoRefresh"
Margin="8,0"
HorizontalAlignment="Left"
IsChecked="True" />
IsChecked="True"
Theme="{StaticResource SimpleToggleSwitch}" />
<TextBlock
Margin="8,0"
VerticalAlignment="Center"
@@ -71,7 +72,8 @@
x:Name="togScrollToEnd"
Margin="8,0"
HorizontalAlignment="Left"
IsChecked="True" />
IsChecked="True"
Theme="{StaticResource SimpleToggleSwitch}" />
</WrapPanel>
<TextBox
Name="txtMsg"

View File

@@ -16,7 +16,7 @@
<DockPanel Classes="Margin8">
<StackPanel
HorizontalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
<Button
@@ -113,7 +113,7 @@
<ListBox
x:Name="clbdestOverride"
HorizontalAlignment="Left"
Classes="Margin4"
Classes="Margin8"
SelectionMode="Multiple"
Theme="{DynamicResource PureCardRadioGroupListBox}" />
</StackPanel>
@@ -309,12 +309,12 @@
x:Name="txtUpMbps"
Width="90"
Classes="Margin8"
ToolTip.Tip="Up" />
Watermark="Up" />
<TextBox
x:Name="txtDownMbps"
Width="90"
Classes="Margin8"
ToolTip.Tip="Down" />
Watermark="Down" />
</StackPanel>
<TextBlock

View File

@@ -75,7 +75,7 @@
Width="200"
Margin="4,0"
VerticalContentAlignment="Center"
ToolTip.Tip="{x:Static resx:ResUI.MsgServerTitle}" />
Watermark="{x:Static resx:ResUI.MsgServerTitle}" />
</WrapPanel>
<DataGrid
x:Name="lstProfiles"

View File

@@ -32,27 +32,27 @@
Grid.Row="0"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="outboundTag" />
<ComboBox
x:Name="cmbOutboundTag"
Grid.Row="0"
Grid.Column="1"
Width="200"
Classes="Margin4"
Classes="Margin8"
MaxDropDownHeight="1000" />
<TextBlock
Grid.Row="0"
Grid.Column="2"
HorizontalAlignment="Left"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbRuleMatchingTips}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="port" />
<TextBox
x:Name="txtPort"
@@ -60,29 +60,29 @@
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
Classes="Margin4" />
Classes="Margin8" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
VerticalAlignment="Center"
Classes="Margin4">
<Button Click="linkRuleobjectDoc_Click">
Classes="Margin8">
<HyperlinkButton Classes="WithIcon" Click="linkRuleobjectDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbRuleobjectDoc}" />
</Button>
</HyperlinkButton>
</TextBlock>
<TextBlock
Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="protocol" />
<ListBox
x:Name="clbProtocol"
Grid.Row="2"
Grid.Column="1"
HorizontalAlignment="Left"
Classes="Margin4"
Classes="Margin8"
SelectionMode="Multiple"
Theme="{DynamicResource PureCardRadioGroupListBox}" />
@@ -90,13 +90,13 @@
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="inboundTag" />
<ListBox
x:Name="clbInboundTag"
Grid.Row="3"
Grid.Column="1"
Classes="Margin4"
Classes="Margin8"
SelectionMode="Multiple"
Theme="{DynamicResource PureCardRadioGroupListBox}" />
@@ -104,34 +104,34 @@
Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="network" />
<ComboBox
x:Name="cmbNetwork"
Grid.Row="4"
Grid.Column="1"
Width="200"
Classes="Margin4"
Classes="Margin8"
MaxDropDownHeight="1000" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="enabled" />
<ToggleSwitch
x:Name="togEnabled"
Grid.Row="5"
Grid.Column="1"
HorizontalAlignment="Left"
Classes="Margin4" />
Classes="Margin8" />
<TextBlock
Grid.Row="5"
Grid.Column="2"
HorizontalAlignment="Left"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbRoutingTips}" />
</Grid>

View File

@@ -62,7 +62,7 @@
Grid.Row="0"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvRemarks}" />
<StackPanel
Grid.Row="0"
@@ -76,25 +76,25 @@
Width="300"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
TextWrapping="Wrap" />
<TextBlock
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvSort}" />
<TextBox
x:Name="txtSort"
Width="100"
HorizontalAlignment="Left"
Classes="Margin4" />
Classes="Margin8" />
</StackPanel>
<TextBlock
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbdomainStrategy}" />
<StackPanel
Grid.Row="1"
@@ -103,22 +103,22 @@
<ComboBox
x:Name="cmbdomainStrategy"
Width="200"
Classes="Margin4" />
Classes="Margin8" />
<TextBlock
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbdomainStrategy4Singbox}" />
<ComboBox
x:Name="cmbdomainStrategy4Singbox"
Width="200"
Classes="Margin4" />
Classes="Margin8" />
</StackPanel>
<TextBlock
Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvUrl}" />
<TextBox
x:Name="txtUrl"
@@ -127,14 +127,14 @@
Width="600"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
TextWrapping="Wrap" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvCustomIcon}" />
<TextBox
x:Name="txtCustomIcon"
@@ -143,23 +143,23 @@
Width="600"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
TextWrapping="Wrap" />
<Button
x:Name="btnBrowseCustomIcon"
Grid.Row="3"
Grid.Column="2"
Classes="Margin4"
Classes="Margin8"
Content="{x:Static resx:ResUI.TbBrowse}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4">
<Button Click="linkCustomRulesetPath4Singbox">
Classes="Margin8">
<HyperlinkButton Classes="WithIcon" Click="linkCustomRulesetPath4Singbox">
<TextBlock Text="{x:Static resx:ResUI.LvCustomRulesetPath4Singbox}" />
</Button>
</HyperlinkButton>
</TextBlock>
<TextBox
x:Name="txtCustomRulesetPath4Singbox"
@@ -168,13 +168,13 @@
Width="600"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
TextWrapping="Wrap" />
<Button
x:Name="btnBrowseCustomRulesetPath4Singbox"
Grid.Row="4"
Grid.Column="2"
Classes="Margin4"
Classes="Margin8"
Content="{x:Static resx:ResUI.TbBrowse}" />
</Grid>

View File

@@ -26,9 +26,9 @@
</Menu>
<TextBlock Margin="8,0,0,0" VerticalAlignment="Center">
<Button Click="linkdomainStrategy_Click">
<HyperlinkButton Classes="WithIcon" Click="linkdomainStrategy_Click">
<TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy}" />
</Button>
</HyperlinkButton>
</TextBlock>
<ComboBox
x:Name="cmbdomainStrategy"
@@ -45,9 +45,9 @@
Margin="8,0,0,0" />
<Separator />
<TextBlock Margin="8,0,0,0" VerticalAlignment="Center">
<Button Click="linkdomainStrategy4Singbox_Click">
<HyperlinkButton Classes="WithIcon" Click="linkdomainStrategy4Singbox_Click">
<TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy4Singbox}" />
</Button>
</HyperlinkButton>
</TextBlock>
<ComboBox
x:Name="cmbdomainStrategy4Singbox"

View File

@@ -17,7 +17,7 @@
<DockPanel Classes="Margin8">
<StackPanel
HorizontalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
<Button
@@ -60,14 +60,14 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.menuSubscription}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvRemarks}" />
<TextBox
@@ -75,53 +75,53 @@
Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
TextWrapping="Wrap" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvUrl}" />
<TextBox
x:Name="txtUrl"
Grid.Row="2"
Grid.Column="1"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
TextWrapping="Wrap"
ToolTip.Tip="{x:Static resx:ResUI.SubUrlTips}" />
Watermark="{x:Static resx:ResUI.SubUrlTips}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvEnabled}" />
<DockPanel
Grid.Row="3"
Grid.Column="1"
Classes="Margin4">
Classes="Margin8">
<ToggleSwitch
x:Name="togEnable"
HorizontalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
DockPanel.Dock="Left" />
<TextBox
x:Name="txtAutoUpdateInterval"
Width="200"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
DockPanel.Dock="Right"
ToolTip.Tip="{x:Static resx:ResUI.SubUrlTips}" />
Watermark="{x:Static resx:ResUI.SubUrlTips}" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvAutoUpdateInterval}" />
</DockPanel>
@@ -129,51 +129,50 @@
Grid.Row="5"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvFilter}" />
<TextBox
x:Name="txtFilter"
Grid.Row="5"
Grid.Column="1"
VerticalAlignment="Center"
Classes="Margin4"
ToolTip.Tip="{x:Static resx:ResUI.SubUrlTips}" />
Classes="Margin8"
Watermark="{x:Static resx:ResUI.SubUrlTips}" />
<TextBlock
Grid.Row="6"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvConvertTarget}" />
<ComboBox
x:Name="cmbConvertTarget"
Grid.Row="6"
Grid.Column="1"
Width="200"
VerticalAlignment=" "
Classes="Margin4"
Classes="Margin8"
ToolTip.Tip="{x:Static resx:ResUI.LvConvertTargetTip}" />
<TextBlock
Grid.Row="7"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvUserAgent}" />
<TextBox
x:Name="txtUserAgent"
Grid.Row="7"
Grid.Column="1"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
TextWrapping="Wrap"
ToolTip.Tip="{x:Static resx:ResUI.SubUrlTips}" />
Watermark="{x:Static resx:ResUI.SubUrlTips}" />
<TextBlock
Grid.Row="8"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvSort}" />
<TextBox
x:Name="txtSort"
@@ -181,42 +180,42 @@
Grid.Column="1"
Width="100"
HorizontalAlignment="Left"
Classes="Margin4" />
Classes="Margin8" />
<TextBlock
Grid.Row="9"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvPrevProfile}" />
<TextBox
x:Name="txtPrevProfile"
Grid.Row="9"
Grid.Column="1"
VerticalAlignment="Center"
Classes="Margin4"
ToolTip.Tip="{x:Static resx:ResUI.LvPrevProfileTip}" />
Classes="Margin8"
Watermark="{x:Static resx:ResUI.LvPrevProfileTip}" />
<TextBlock
Grid.Row="10"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvNextProfile}" />
<TextBox
x:Name="txtNextProfile"
Grid.Row="10"
Grid.Column="1"
VerticalAlignment="Center"
Classes="Margin4"
ToolTip.Tip="{x:Static resx:ResUI.LvPrevProfileTip}" />
Classes="Margin8"
Watermark="{x:Static resx:ResUI.LvPrevProfileTip}" />
<TextBlock
Grid.Row="11"
Grid.Column="0"
Margin="4"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbPreSocksPort4Sub}" />
<TextBox
x:Name="txtPreSocksPort"
@@ -225,15 +224,16 @@
Width="200"
Margin="4"
HorizontalAlignment="Left"
Classes="Margin4"
ToolTip.Tip="{x:Static resx:ResUI.TipPreSocksPort}" />
Classes="Margin8"
ToolTip.Tip="{x:Static resx:ResUI.TipPreSocksPort}"
Watermark="{x:Static resx:ResUI.TipPreSocksPort}" />
<TextBlock
Grid.Row="12"
Grid.Column="0"
Grid.ColumnSpan="2"
VerticalAlignment="Center"
Classes="Margin4"
Classes="Margin8"
Text="{x:Static resx:ResUI.LvMoreUrl}" />
<TextBox
x:Name="txtMoreUrl"
@@ -242,10 +242,10 @@
MinHeight="100"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Classes="TextArea Margin4"
Classes="TextArea Margin8"
MinLines="4"
TextWrapping="Wrap"
ToolTip.Tip="{x:Static resx:ResUI.SubUrlTips}" />
Watermark="{x:Static resx:ResUI.SubUrlTips}" />
</Grid>
</ScrollViewer>
</DockPanel>

View File

@@ -25,9 +25,9 @@
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.3" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.1.3" />
<PackageReference Include="MessageBox.Avalonia" Version="3.1.6" />
<PackageReference Include="Semi.Avalonia" Version="11.1.0.3" />
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.1.0.3" />
<PackageReference Include="ReactiveUI" Version="20.1.1" />
<PackageReference Include="Semi.Avalonia" Version="11.1.0.4" />
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.1.0.4" />
<PackageReference Include="ReactiveUI" Version="20.1.63" />
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
</ItemGroup>

View File

@@ -1,9 +1,9 @@
<Application
x:Class="v2rayN.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
ShutdownMode="OnExplicitShutdown"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
@@ -181,6 +181,23 @@
TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="{DynamicResource StdFontSize-1}" />
</Style>
<Style
x:Key="WindowGlobal"
BasedOn="{StaticResource {x:Type Window}}"
TargetType="{x:Type Window}">
<Setter Property="TextOptions.TextFormattingMode" Value="Ideal" />
<Setter Property="TextOptions.TextRenderingMode" Value="ClearType" />
<Setter Property="TextOptions.TextHintingMode" Value="Fixed" />
</Style>
<Style
x:Key="ViewGlobal"
BasedOn="{StaticResource {x:Type UserControl}}"
TargetType="{x:Type UserControl}">
<Setter Property="TextOptions.TextFormattingMode" Value="Ideal" />
<Setter Property="TextOptions.TextRenderingMode" Value="ClearType" />
<Setter Property="TextOptions.TextHintingMode" Value="Fixed" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -11,7 +11,7 @@ namespace v2rayN.Converters
try
{
var fontFamily = LazyConfig.Instance.Config.uiItem.currentFontFamily;
if (!Utils.IsNullOrEmpty(fontFamily))
if (Utils.IsNotEmpty(fontFamily))
{
var fontPath = Utils.GetFontsPath();
MyFont = new FontFamily(new Uri(@$"file:///{fontPath}\"), $"./#{fontFamily}");

View File

@@ -156,7 +156,7 @@ namespace v2rayN.ViewModels
y => y != null && !y.IsNullOrEmpty())
.Subscribe(c =>
{
if (!Utils.IsNullOrEmpty(CurrentLanguage) && _config.uiItem.currentLanguage != CurrentLanguage)
if (Utils.IsNotEmpty(CurrentLanguage) && _config.uiItem.currentLanguage != CurrentLanguage)
{
_config.uiItem.currentLanguage = CurrentLanguage;
Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage);

View File

@@ -17,10 +17,9 @@
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel Margin="8">

View File

@@ -17,6 +17,9 @@ namespace v2rayN.Views
foreach (ECoreType it in Enum.GetValues(typeof(ECoreType)))
{
if (it == ECoreType.v2rayN)
continue;
//TODO
if (it is ECoreType.clash or ECoreType.clash_meta or ECoreType.SagerNet)
continue;
cmbCoreType.Items.Add(it.ToString());
}

View File

@@ -17,10 +17,9 @@
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="CanResize"
ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel Margin="8">

View File

@@ -79,8 +79,8 @@ namespace v2rayN.Views
});
break;
case EConfigType.Socks:
case EConfigType.Http:
case EConfigType.SOCKS:
case EConfigType.HTTP:
gridSocks.Visibility = Visibility.Visible;
break;
@@ -115,7 +115,7 @@ namespace v2rayN.Views
cmbFingerprint.Text = string.Empty;
break;
case EConfigType.Tuic:
case EConfigType.TUIC:
gridTuic.Visibility = Visibility.Visible;
sepa2.Visibility = Visibility.Collapsed;
gridTransport.Visibility = Visibility.Collapsed;
@@ -129,7 +129,7 @@ namespace v2rayN.Views
});
break;
case EConfigType.Wireguard:
case EConfigType.WireGuard:
gridWireguard.Visibility = Visibility.Visible;
sepa2.Visibility = Visibility.Collapsed;
@@ -162,8 +162,8 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SelectedSource.security, v => v.cmbSecurity3.Text).DisposeWith(disposables);
break;
case EConfigType.Socks:
case EConfigType.Http:
case EConfigType.SOCKS:
case EConfigType.HTTP:
this.Bind(ViewModel, vm => vm.SelectedSource.id, v => v.txtId4.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.security, v => v.txtSecurity4.Text).DisposeWith(disposables);
break;
@@ -184,13 +184,13 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SelectedSource.path, v => v.txtPath7.Text).DisposeWith(disposables);
break;
case EConfigType.Tuic:
case EConfigType.TUIC:
this.Bind(ViewModel, vm => vm.SelectedSource.id, v => v.txtId8.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.security, v => v.txtSecurity8.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.headerType, v => v.cmbHeaderType8.Text).DisposeWith(disposables);
break;
case EConfigType.Wireguard:
case EConfigType.WireGuard:
this.Bind(ViewModel, vm => vm.SelectedSource.id, v => v.txtId9.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.publicKey, v => v.txtPublicKey9.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.path, v => v.txtPath9.Text).DisposeWith(disposables);

View File

@@ -12,6 +12,7 @@
d:DesignHeight="600"
d:DesignWidth="800"
x:TypeArguments="vms:BackupAndRestoreViewModel"
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>

View File

@@ -26,7 +26,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SelectedSource.userName, v => v.txtWebDavUserName.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.password, v => v.txtWebDavPassword.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.dirName, v => v.txtWebDavDirName.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.WebDavCheckCmd, v => v.menuWebDavCheck).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RemoteBackupCmd, v => v.menuRemoteBackup).DisposeWith(disposables);

View File

@@ -12,6 +12,7 @@
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="vms:CheckUpdateViewModel"
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<DockPanel Margin="16">

View File

@@ -20,6 +20,15 @@
DockPanel.Dock="Top"
Orientation="Horizontal">
<TextBox
x:Name="txtHostFilter"
Width="200"
Margin="8,0"
VerticalContentAlignment="Center"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.ConnectionsHostFilterTitle}"
materialDesign:TextFieldAssist.HasClearButton="True"
Style="{StaticResource DefTextBox}" />
<TextBlock
Margin="8,0"
VerticalAlignment="Center"

View File

@@ -23,6 +23,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.ConnectionCloseCmd, v => v.menuConnectionClose).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.SortingSelected, v => v.cmbSorting.SelectedIndex).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);

View File

@@ -1,18 +1,19 @@
<reactiveui:ReactiveUserControl
x:Class="v2rayN.Views.ClashProxiesView"
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:converters="clr-namespace:v2rayN.Converters"
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:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
xmlns:converters="clr-namespace:v2rayN.Converters"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="vms:ClashProxiesViewModel"
KeyDown="ProxiesView_KeyDown"
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />

View File

@@ -17,10 +17,9 @@
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel Margin="8">
@@ -117,7 +116,7 @@
x:Name="txtnormalDNS"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Stretch"
materialDesign:HintAssist.Hint="Http/Socks"
materialDesign:HintAssist.Hint="HTTP/SOCKS"
AcceptsReturn="True"
BorderThickness="1"
Style="{StaticResource MaterialDesignOutlinedTextBox}"
@@ -186,7 +185,7 @@
x:Name="txtnormalDNS2"
Grid.Column="0"
VerticalAlignment="Stretch"
materialDesign:HintAssist.Hint="Http/Socks"
materialDesign:HintAssist.Hint="HTTP/SOCKS"
AcceptsReturn="True"
BorderThickness="1"
Style="{StaticResource MaterialDesignOutlinedTextBox}"

View File

@@ -18,10 +18,9 @@
KeyDown="GlobalHotkeySettingWindow_KeyDown"
ResizeMode="NoResize"
ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel Margin="8">

View File

@@ -18,10 +18,9 @@
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ShowInTaskbar="True"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources>

View File

@@ -36,8 +36,9 @@ namespace v2rayN.Views
menuCheckUpdate.Click += MenuCheckUpdate_Click;
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
var IsAdministrator = WindowsUtils.IsAdministrator();
MessageBus.Current.Listen<string>(Global.CommandSendSnackMsg).Subscribe(x => DelegateSnackMsg(x));
ViewModel = new MainWindowViewModel(UpdateViewHandler);
ViewModel = new MainWindowViewModel(IsAdministrator, UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
WindowsHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null);
@@ -143,20 +144,7 @@ namespace v2rayN.Views
}
});
var IsAdministrator = WindowsUtils.IsAdministrator();
ViewModel.IsAdministrator = IsAdministrator;
this.Title = $"{Utils.GetVersion()} - {(IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
if (_config.tunModeItem.enableTun)
{
if (IsAdministrator)
{
ViewModel.EnableTun = true;
}
else
{
_config.tunModeItem.enableTun = ViewModel.EnableTun = false;
}
}
if (!_config.guiItem.enableHWA)
{
@@ -505,7 +493,8 @@ namespace v2rayN.Views
{
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
foreach (var it in coreInfo
.Where(t => t.coreType != ECoreType.v2fly
.Where(t => t.coreType != ECoreType.v2fly
&& t.coreType != ECoreType.SagerNet
&& t.coreType != ECoreType.clash
&& t.coreType != ECoreType.clash_meta
&& t.coreType != ECoreType.hysteria))

View File

@@ -11,6 +11,7 @@
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="vms:MsgViewModel"
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<DockPanel Margin="2">
<WrapPanel

View File

@@ -17,10 +17,9 @@
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel Margin="8">

View File

@@ -13,6 +13,7 @@
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="vms:ProfilesViewModel"
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />

View File

@@ -338,24 +338,16 @@ namespace v2rayN.Views
item2.Width = item.Width;
item2.DisplayIndex = displayIndex++;
}
if (item.Name.StartsWith("to"))
{
if (!_config.guiItem.enableStatistics)
{
item2.Visibility = Visibility.Hidden;
}
}
}
}
}
if (!_config.guiItem.enableStatistics)
{
colTodayUp.Visibility =
colTodayDown.Visibility =
colTotalUp.Visibility =
colTotalDown.Visibility = Visibility.Hidden;
}
else
{
colTodayUp.Visibility =
colTodayDown.Visibility =
colTotalUp.Visibility =
colTotalDown.Visibility = Visibility.Visible;
}
}
private void StorageUI()

View File

@@ -8,6 +8,7 @@
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
d:DesignHeight="300"
d:DesignWidth="300"
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<Grid Margin="30">
<Grid.RowDefinitions>

View File

@@ -1,14 +1,14 @@
<reactiveui:ReactiveWindow
x:Class="v2rayN.Views.RoutingRuleDetailsWindow"
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:conv="clr-namespace:v2rayN.Converters"
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:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
xmlns:conv="clr-namespace:v2rayN.Converters"
Title="{x:Static resx:ResUI.menuRoutingRuleDetailsSetting}"
Width="900"
Height="700"
@@ -17,10 +17,9 @@
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel>

View File

@@ -1,14 +1,14 @@
<reactiveui:ReactiveWindow
x:Class="v2rayN.Views.RoutingRuleSettingWindow"
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:conv="clr-namespace:v2rayN.Converters"
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:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
xmlns:conv="clr-namespace:v2rayN.Converters"
Title="{x:Static resx:ResUI.menuRoutingRuleSetting}"
Width="960"
Height="700"
@@ -17,10 +17,9 @@
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel>

View File

@@ -17,10 +17,9 @@
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources>

View File

@@ -1,14 +1,14 @@
<reactiveui:ReactiveWindow
x:Class="v2rayN.Views.SubEditWindow"
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:conv="clr-namespace:v2rayN.Converters"
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:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
xmlns:conv="clr-namespace:v2rayN.Converters"
Title="{x:Static resx:ResUI.menuSubSetting}"
Width="700"
Height="600"
@@ -17,10 +17,9 @@
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources>

View File

@@ -17,10 +17,9 @@
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<materialDesign:DialogHost

View File

@@ -1,15 +1,16 @@
<reactiveui:ReactiveUserControl
x:Class="v2rayN.Views.ThemeSettingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:reactiveui="http://reactiveui.net"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:v2rayN.ViewModels"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="vms:ThemeSettingViewModel"
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<StackPanel Margin="8">
<Grid>

View File

@@ -19,7 +19,7 @@
<PackageReference Include="TaskScheduler" Version="2.11.0" />
<PackageReference Include="ZXing.Net.Bindings.Windows.Compatibility" Version="0.16.12" />
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
<PackageReference Include="ReactiveUI.WPF" Version="20.1.1" />
<PackageReference Include="ReactiveUI.WPF" Version="20.1.63" />
</ItemGroup>
<ItemGroup>