Compare commits

..

18 Commits
6.52 ... 6.55

Author SHA1 Message Date
2dust
d893ee4829 up 6.55 2024-08-05 14:41:54 +08:00
2dust
dfc5ec0705 Improve UI 2024-08-05 14:39:04 +08:00
2dust
8023eb74c9 Bug fix 2024-08-04 19:26:01 +08:00
2dust
bb4d3997ad Bug fix
https://github.com/2dust/v2rayN/issues/5467
2024-08-04 09:40:33 +08:00
2dust
7ede3af762 up 6.54 2024-08-03 16:02:42 +08:00
2dust
97ea1c7a9e Add toolTip 2024-08-03 15:59:00 +08:00
2dust
43bb2c0fb8 Bug fix
https://github.com/2dust/v2rayN/issues/5462
2024-08-03 15:37:47 +08:00
2dust
6e7196bb27 Bug fix
https://github.com/2dust/v2rayN/issues/5437
2024-07-31 20:13:41 +08:00
2dust
87a71d58e8 Fix
https://github.com/2dust/v2rayN/issues/5438
2024-07-30 16:22:54 +08:00
2dust
32ffd43fe3 Bug fix
https://github.com/2dust/v2rayN/issues/5425
2024-07-30 16:06:43 +08:00
2dust
6500c8d85e up 6.53 2024-07-26 11:05:53 +08:00
2dust
9866d436da Add Outbound DNS address
https://github.com/2dust/v2rayN/issues/5387
2024-07-26 11:00:07 +08:00
2dust
0f4884d9d8 Improve and refactor the code 2024-07-25 10:26:39 +08:00
2dust
5a81441351 Adjust resx 2024-07-24 20:14:07 +08:00
2dust
e8721bfb6b Default dns changed to whitelist 2024-07-24 20:01:26 +08:00
2dust
1b09d95209 Improve UI 2024-07-24 19:51:13 +08:00
Jabin Kong
35f3b5a50e 1 (#5394) 2024-07-23 20:41:00 +08:00
2dust
ff5203a561 alpn h2,h3 2024-07-23 20:33:02 +08:00
36 changed files with 763 additions and 459 deletions

View File

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

View File

@@ -1,9 +1,9 @@
<Application <Application
x:Class="v2rayN.App" x:Class="v2rayN.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters" xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
ShutdownMode="OnExplicitShutdown" ShutdownMode="OnExplicitShutdown"
StartupUri="Views/MainWindow.xaml"> StartupUri="Views/MainWindow.xaml">
<Application.Resources> <Application.Resources>
@@ -62,11 +62,9 @@
</Style> </Style>
<Style TargetType="{x:Type TextElement}"> <Style TargetType="{x:Type TextElement}">
<Setter Property="FontWeight" Value="Regular" /> <Setter Property="FontWeight" Value="Regular" />
<Setter Property="Foreground" Value="{DynamicResource MaterialDesignBody}" />
</Style> </Style>
<Style TargetType="{x:Type TextBlock}"> <Style TargetType="{x:Type TextBlock}">
<Setter Property="FontWeight" Value="Regular" /> <Setter Property="FontWeight" Value="Regular" />
<Setter Property="Foreground" Value="{DynamicResource MaterialDesignBody}" />
</Style> </Style>
<Style x:Key="lvItemSelected" TargetType="{x:Type ListViewItem}"> <Style x:Key="lvItemSelected" TargetType="{x:Type ListViewItem}">
<Setter Property="Margin" Value="2" /> <Setter Property="Margin" Value="2" />

View File

@@ -176,8 +176,10 @@ namespace v2rayN
public static readonly List<string> AllowInsecure = new() { "true", "false", "" }; public static readonly List<string> AllowInsecure = new() { "true", "false", "" };
public static readonly List<string> DomainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" }; public static readonly List<string> DomainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" };
public static readonly List<string> SingboxDomainStrategy4Out = new() { "ipv4_only", "prefer_ipv4", "prefer_ipv6", "ipv6_only", "" }; public static readonly List<string> SingboxDomainStrategy4Out = new() { "ipv4_only", "prefer_ipv4", "prefer_ipv6", "ipv6_only", "" };
public static readonly List<string> DomainDNSAddress = ["223.5.5.5", "223.6.6.6", "localhost"];
public static readonly List<string> SingboxDomainDNSAddress = ["223.5.5.5", "223.6.6.6", "dhcp://auto"];
public static readonly List<string> Languages = new() { "zh-Hans", "zh-Hant", "en", "fa-Ir", "ru" }; public static readonly List<string> Languages = new() { "zh-Hans", "zh-Hant", "en", "fa-Ir", "ru" };
public static readonly List<string> Alpns = new() { "h3", "h2", "http/1.1", "h3,h2,http/1.1", "h3,h2", "h2,http/1.1", "" }; public static readonly List<string> Alpns = new() { "h3", "h2", "http/1.1", "h3,h2", "h2,http/1.1", "h3,h2,http/1.1", "" };
public static readonly List<string> LogLevels = new() { "debug", "info", "warning", "error", "none" }; public static readonly List<string> LogLevels = new() { "debug", "info", "warning", "error", "none" };
public static readonly List<string> InboundTags = new() { "socks", "http", "socks2", "http2" }; public static readonly List<string> InboundTags = new() { "socks", "http", "socks2", "http2" };
public static readonly List<string> RuleProtocols = new() { "http", "tls", "bittorrent" }; public static readonly List<string> RuleProtocols = new() { "http", "tls", "bittorrent" };

View File

@@ -197,6 +197,15 @@ namespace v2rayN.Handler
} }
config.clashUIItem ??= new(); config.clashUIItem ??= new();
if (config.systemProxyItem == null)
{
config.systemProxyItem = new()
{
systemProxyExceptions = config.systemProxyExceptions,
systemProxyAdvancedProtocol = config.systemProxyAdvancedProtocol,
};
}
LazyConfig.Instance.SetConfig(config); LazyConfig.Instance.SetConfig(config);
return 0; return 0;
} }

View File

@@ -389,16 +389,25 @@ namespace v2rayN.Handler.CoreConfig
return -1; return -1;
} }
if (node.address == Global.CoreMultipleLoadConfigFileName)
{
var txtFile = File.ReadAllText(addressFileName); var txtFile = File.ReadAllText(addressFileName);
var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(txtFile); var singboxConfig = JsonUtils.Deserialize<SingboxConfig>(txtFile);
if (singboxConfig == null) if (singboxConfig == null)
{ {
msg = ResUI.FailedConversionConfiguration; File.Copy(addressFileName, fileName);
return -1;
} }
else
{
GenInbounds(singboxConfig);
GenExperimental(singboxConfig); GenExperimental(singboxConfig);
JsonUtils.ToFile(singboxConfig, fileName, false); JsonUtils.ToFile(singboxConfig, fileName, false);
}
}
else
{
File.Copy(addressFileName, fileName);
}
//check again //check again
if (!File.Exists(fileName)) if (!File.Exists(fileName))
@@ -1180,7 +1189,7 @@ namespace v2rayN.Handler.CoreConfig
} }
singboxConfig.dns = dns4Sbox; singboxConfig.dns = dns4Sbox;
GenDnsDomains(node, singboxConfig, item?.domainStrategy4Freedom); GenDnsDomains(node, singboxConfig, item);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -1189,7 +1198,7 @@ namespace v2rayN.Handler.CoreConfig
return 0; return 0;
} }
private int GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, string? strategy) private int GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem)
{ {
var dns4Sbox = singboxConfig.dns ?? new(); var dns4Sbox = singboxConfig.dns ?? new();
dns4Sbox.servers ??= []; dns4Sbox.servers ??= [];
@@ -1199,9 +1208,9 @@ namespace v2rayN.Handler.CoreConfig
dns4Sbox.servers.Add(new() dns4Sbox.servers.Add(new()
{ {
tag = tag, tag = tag,
address = "223.5.5.5", address = Utils.IsNullOrEmpty(dNSItem?.domainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : dNSItem?.domainDNSAddress,
detour = Global.DirectTag, detour = Global.DirectTag,
strategy = Utils.IsNullOrEmpty(strategy) ? null : strategy, strategy = Utils.IsNullOrEmpty(dNSItem?.domainStrategy4Freedom) ? null : dNSItem?.domainStrategy4Freedom,
}); });
dns4Sbox.rules.Insert(0, new() dns4Sbox.rules.Insert(0, new()
{ {

View File

@@ -1073,7 +1073,7 @@ namespace v2rayN.Handler.CoreConfig
} }
} }
GenDnsDomains(node, obj); GenDnsDomains(node, obj, item);
v2rayConfig.dns = obj; v2rayConfig.dns = obj;
} }
@@ -1084,7 +1084,7 @@ namespace v2rayN.Handler.CoreConfig
return 0; return 0;
} }
private int GenDnsDomains(ProfileItem? node, JsonNode dns) private int GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem)
{ {
if (node == null) if (node == null)
{ return 0; } { return 0; }
@@ -1095,7 +1095,7 @@ namespace v2rayN.Handler.CoreConfig
{ {
var dnsServer = new DnsServer4Ray() var dnsServer = new DnsServer4Ray()
{ {
address = "223.5.5.5", address = Utils.IsNullOrEmpty(dNSItem?.domainDNSAddress) ? Global.DomainDNSAddress.FirstOrDefault() : dNSItem?.domainDNSAddress,
domains = [node.address] domains = [node.address]
}; };
servers.AsArray().Insert(0, JsonUtils.SerializeToNode(dnsServer)); servers.AsArray().Insert(0, JsonUtils.SerializeToNode(dnsServer));

View File

@@ -22,7 +22,7 @@ namespace v2rayN.Handler
{ {
try try
{ {
int index = (int)config.sysProxyType; int index = (int)config.systemProxyItem.sysProxyType;
//Load from routing setting //Load from routing setting
var createdIcon = GetNotifyIcon4Routing(config); var createdIcon = GetNotifyIcon4Routing(config);
@@ -56,7 +56,7 @@ namespace v2rayN.Handler
public System.Windows.Media.ImageSource GetAppIcon(Config config) public System.Windows.Media.ImageSource GetAppIcon(Config config)
{ {
int index = 1; int index = 1;
switch (config.sysProxyType) switch (config.systemProxyItem.sysProxyType)
{ {
case ESysProxyType.ForcedClear: case ESysProxyType.ForcedClear:
index = 1; index = 1;
@@ -90,7 +90,7 @@ namespace v2rayN.Handler
} }
Color color = ColorTranslator.FromHtml("#3399CC"); Color color = ColorTranslator.FromHtml("#3399CC");
int index = (int)config.sysProxyType; int index = (int)config.systemProxyItem.sysProxyType;
if (index > 0) if (index > 0)
{ {
color = (new[] { Color.Red, Color.Purple, Color.DarkGreen, Color.Orange, Color.DarkSlateBlue, Color.RoyalBlue })[index - 1]; color = (new[] { Color.Red, Color.Purple, Color.DarkGreen, Color.Orange, Color.DarkSlateBlue, Color.RoyalBlue })[index - 1];

View File

@@ -11,7 +11,7 @@ namespace v2rayN.Handler
public static bool UpdateSysProxy(Config config, bool forceDisable) public static bool UpdateSysProxy(Config config, bool forceDisable)
{ {
var type = config.sysProxyType; var type = config.systemProxyItem.sysProxyType;
if (forceDisable && type != ESysProxyType.Unchanged) if (forceDisable && type != ESysProxyType.Unchanged)
{ {
@@ -29,16 +29,20 @@ namespace v2rayN.Handler
} }
if (type == ESysProxyType.ForcedChange) if (type == ESysProxyType.ForcedChange)
{ {
var strExceptions = $"<local>;{config.constItem.defIEProxyExceptions};{config.systemProxyExceptions}"; var strExceptions = "";
if (config.systemProxyItem.notProxyLocalAddress)
{
strExceptions = $"<local>;{config.constItem.defIEProxyExceptions};{config.systemProxyItem.systemProxyExceptions}";
}
var strProxy = string.Empty; var strProxy = string.Empty;
if (Utils.IsNullOrEmpty(config.systemProxyAdvancedProtocol)) if (Utils.IsNullOrEmpty(config.systemProxyItem.systemProxyAdvancedProtocol))
{ {
strProxy = $"{Global.Loopback}:{port}"; strProxy = $"{Global.Loopback}:{port}";
} }
else else
{ {
strProxy = config.systemProxyAdvancedProtocol strProxy = config.systemProxyItem.systemProxyAdvancedProtocol
.Replace("{ip}", Global.Loopback) .Replace("{ip}", Global.Loopback)
.Replace("{http_port}", port.ToString()) .Replace("{http_port}", port.ToString())
.Replace("{socks_port}", portSocks.ToString()); .Replace("{socks_port}", portSocks.ToString());

View File

@@ -12,7 +12,6 @@ namespace v2rayN.Models
public string indexId { get; set; } public string indexId { get; set; }
public string subIndexId { get; set; } public string subIndexId { get; set; }
public ESysProxyType sysProxyType { get; set; }
public string systemProxyExceptions { get; set; } public string systemProxyExceptions { get; set; }
public string systemProxyAdvancedProtocol { get; set; } public string systemProxyAdvancedProtocol { get; set; }
@@ -47,6 +46,7 @@ namespace v2rayN.Models
public Mux4SboxItem mux4SboxItem { get; set; } public Mux4SboxItem mux4SboxItem { get; set; }
public HysteriaItem hysteriaItem { get; set; } public HysteriaItem hysteriaItem { get; set; }
public ClashUIItem clashUIItem { get; set; } public ClashUIItem clashUIItem { get; set; }
public SystemProxyItem systemProxyItem { get; set; }
public List<InItem> inbound { get; set; } public List<InItem> inbound { get; set; }
public List<KeyEventItem> globalHotkeys { get; set; } public List<KeyEventItem> globalHotkeys { get; set; }
public List<CoreTypeItem> coreTypeItem { get; set; } public List<CoreTypeItem> coreTypeItem { get; set; }

View File

@@ -119,7 +119,7 @@ namespace v2rayN.Models
public double mainHeight { get; set; } public double mainHeight { get; set; }
public double mainGirdHeight1 { get; set; } public double mainGirdHeight1 { get; set; }
public double mainGirdHeight2 { get; set; } public double mainGirdHeight2 { get; set; }
public EGirdOrientation mainGirdOrientation { get; set; } public EGirdOrientation mainGirdOrientation { get; set; } = EGirdOrientation.Vertical;
public bool colorModeDark { get; set; } public bool colorModeDark { get; set; }
public bool followSystemTheme { get; set; } public bool followSystemTheme { get; set; }
public string? colorPrimaryName { get; set; } public string? colorPrimaryName { get; set; }
@@ -227,4 +227,13 @@ namespace v2rayN.Models
public bool connectionsAutoRefresh { get; set; } public bool connectionsAutoRefresh { get; set; }
public int connectionsRefreshInterval { get; set; } = 2; public int connectionsRefreshInterval { get; set; } = 2;
} }
[Serializable]
public class SystemProxyItem
{
public ESysProxyType sysProxyType { get; set; }
public string systemProxyExceptions { get; set; }
public bool notProxyLocalAddress { get; set; } = true;
public string systemProxyAdvancedProtocol { get; set; }
}
} }

View File

@@ -16,5 +16,6 @@ namespace v2rayN.Models
public string? normalDNS { get; set; } public string? normalDNS { get; set; }
public string? tunDNS { get; set; } public string? tunDNS { get; set; }
public string? domainStrategy4Freedom { get; set; } public string? domainStrategy4Freedom { get; set; }
public string? domainDNSAddress { get; set; }
} }
} }

View File

@@ -331,7 +331,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Automatic update interval(minutes) 的本地化字符串。 /// 查找类似 Automatic update interval (minutes) 的本地化字符串。
/// </summary> /// </summary>
public static string LvAutoUpdateInterval { public static string LvAutoUpdateInterval {
get { get {
@@ -385,7 +385,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Enabled Update 的本地化字符串。 /// 查找类似 Enable update 的本地化字符串。
/// </summary> /// </summary>
public static string LvEnabled { public static string LvEnabled {
get { get {
@@ -412,7 +412,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 More urls, separated by commas;Subscription conversion will be invalid 的本地化字符串。 /// 查找类似 More URLs, separated by commas; Subscription conversion will be invalid 的本地化字符串。
/// </summary> /// </summary>
public static string LvMoreUrl { public static string LvMoreUrl {
get { get {
@@ -996,6 +996,15 @@ namespace v2rayN.Resx {
} }
} }
/// <summary>
/// 查找类似 Auto column width adjustment 的本地化字符串。
/// </summary>
public static string menuProfileAutofitColumnWidth {
get {
return ResourceManager.GetString("menuProfileAutofitColumnWidth", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Promotion 的本地化字符串。 /// 查找类似 Promotion 的本地化字符串。
/// </summary> /// </summary>
@@ -1258,7 +1267,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Multi-Server Preferred Latency 的本地化字符串。 /// 查找类似 Multi-Server lowest latency 的本地化字符串。
/// </summary> /// </summary>
public static string menuSetDefaultMultipleServer { public static string menuSetDefaultMultipleServer {
get { get {
@@ -1357,7 +1366,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Subscription group 的本地化字符串。 /// 查找类似 Subscription Group 的本地化字符串。
/// </summary> /// </summary>
public static string menuSubscription { public static string menuSubscription {
get { get {
@@ -1384,7 +1393,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Update subscription without proxy 的本地化字符串。 /// 查找类似 Update subscriptions without proxy 的本地化字符串。
/// </summary> /// </summary>
public static string menuSubUpdate { public static string menuSubUpdate {
get { get {
@@ -1393,7 +1402,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Update subscription with proxy 的本地化字符串。 /// 查找类似 Update subscriptions with proxy 的本地化字符串。
/// </summary> /// </summary>
public static string menuSubUpdateViaProxy { public static string menuSubUpdateViaProxy {
get { get {
@@ -1609,7 +1618,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Update subscription end 的本地化字符串。 /// 查找类似 Update subscriptions end 的本地化字符串。
/// </summary> /// </summary>
public static string MsgUpdateSubscriptionEnd { public static string MsgUpdateSubscriptionEnd {
get { get {
@@ -1618,7 +1627,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Update subscription starts 的本地化字符串。 /// 查找类似 Update subscriptions start 的本地化字符串。
/// </summary> /// </summary>
public static string MsgUpdateSubscriptionStart { public static string MsgUpdateSubscriptionStart {
get { get {
@@ -1888,7 +1897,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Group please leave blank here 的本地化字符串。 /// 查找类似 For group please leave blank here 的本地化字符串。
/// </summary> /// </summary>
public static string SubUrlTips { public static string SubUrlTips {
get { get {
@@ -2662,6 +2671,15 @@ namespace v2rayN.Resx {
} }
} }
/// <summary>
/// 查找类似 Outbound DNS address 的本地化字符串。
/// </summary>
public static string TbSettingsDomainDNSAddress {
get {
return ResourceManager.GetString("TbSettingsDomainDNSAddress", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Outbound Freedom domainStrategy 的本地化字符串。 /// 查找类似 Outbound Freedom domainStrategy 的本地化字符串。
/// </summary> /// </summary>
@@ -2932,6 +2950,15 @@ namespace v2rayN.Resx {
} }
} }
/// <summary>
/// 查找类似 Do not use proxy servers for local (intranet) addresses 的本地化字符串。
/// </summary>
public static string TbSettingsNotProxyLocalAddress {
get {
return ResourceManager.GetString("TbSettingsNotProxyLocalAddress", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Auth pass 的本地化字符串。 /// 查找类似 Auth pass 的本地化字符串。
/// </summary> /// </summary>

View File

@@ -925,6 +925,9 @@
<data name="TbSettingsRouteOnly" xml:space="preserve"> <data name="TbSettingsRouteOnly" xml:space="preserve">
<value>فقط مسیر</value> <value>فقط مسیر</value>
</data> </data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>يەرلىك (Intranet) ئادرېسلارغا ۋاكالەتچى مۇلازىمېتىر ئىشلەتمەڭ</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve"> <data name="menuMixedTestServer" xml:space="preserve">
<value>One-click test Latency and speed (Ctrl+E)</value> <value>One-click test Latency and speed (Ctrl+E)</value>
</data> </data>

View File

@@ -928,6 +928,9 @@
<data name="TbSettingsRouteOnly" xml:space="preserve"> <data name="TbSettingsRouteOnly" xml:space="preserve">
<value>RouteOnly</value> <value>RouteOnly</value>
</data> </data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>Do not use proxy servers for local (intranet) addresses</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve"> <data name="menuMixedTestServer" xml:space="preserve">
<value>One-click multi test Latency and speed (Ctrl+E)</value> <value>One-click multi test Latency and speed (Ctrl+E)</value>
</data> </data>
@@ -1247,7 +1250,7 @@
<value>Default domain strategy for outbound</value> <value>Default domain strategy for outbound</value>
</data> </data>
<data name="menuSetDefaultMultipleServer" xml:space="preserve"> <data name="menuSetDefaultMultipleServer" xml:space="preserve">
<value>Multi-Server Preferred Latency</value> <value>Multi-Server lowest latency</value>
</data> </data>
<data name="TbSettingsMainGirdOrientation" xml:space="preserve"> <data name="TbSettingsMainGirdOrientation" xml:space="preserve">
<value>Main layout orientation(Require restart)</value> <value>Main layout orientation(Require restart)</value>
@@ -1255,4 +1258,10 @@
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve"> <data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
<value>Multi-server load balancing</value> <value>Multi-server load balancing</value>
</data> </data>
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
<value>Outbound DNS address</value>
</data>
<data name="menuProfileAutofitColumnWidth" xml:space="preserve">
<value>Auto column width adjustment</value>
</data>
</root> </root>

View File

@@ -934,6 +934,9 @@
<data name="TbSettingsRouteOnly" xml:space="preserve"> <data name="TbSettingsRouteOnly" xml:space="preserve">
<value>Только маршрут</value> <value>Только маршрут</value>
</data> </data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>Не используйте прокси-серверы для локальных (интранет) адресов</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve"> <data name="menuMixedTestServer" xml:space="preserve">
<value>Тест задержки и скорости всех серверов (Ctrl+E)</value> <value>Тест задержки и скорости всех серверов (Ctrl+E)</value>
</data> </data>

View File

@@ -928,6 +928,9 @@
<data name="TbSettingsRouteOnly" xml:space="preserve"> <data name="TbSettingsRouteOnly" xml:space="preserve">
<value>RouteOnly</value> <value>RouteOnly</value>
</data> </data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>请勿将代理服务器用于本地Intranet地址</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve"> <data name="menuMixedTestServer" xml:space="preserve">
<value>一键多线程测试延迟和速度 (Ctrl+E)</value> <value>一键多线程测试延迟和速度 (Ctrl+E)</value>
</data> </data>
@@ -1244,7 +1247,7 @@
<value>Outbound默认解析策略</value> <value>Outbound默认解析策略</value>
</data> </data>
<data name="menuSetDefaultMultipleServer" xml:space="preserve"> <data name="menuSetDefaultMultipleServer" xml:space="preserve">
<value>多服务器优选延迟 (多选)</value> <value>多服务器最低延迟 (多选)</value>
</data> </data>
<data name="TbSettingsMainGirdOrientation" xml:space="preserve"> <data name="TbSettingsMainGirdOrientation" xml:space="preserve">
<value>主界面布局方向(需重启)</value> <value>主界面布局方向(需重启)</value>
@@ -1252,4 +1255,10 @@
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve"> <data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
<value>多服务器负载均衡 (多选)</value> <value>多服务器负载均衡 (多选)</value>
</data> </data>
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
<value>Outbound域名解析地址</value>
</data>
<data name="menuProfileAutofitColumnWidth" xml:space="preserve">
<value>自动调整列宽</value>
</data>
</root> </root>

View File

@@ -928,6 +928,9 @@
<data name="TbSettingsRouteOnly" xml:space="preserve"> <data name="TbSettingsRouteOnly" xml:space="preserve">
<value>RouteOnly</value> <value>RouteOnly</value>
</data> </data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>請勿將代理伺服器用於本機Intranet位址</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve"> <data name="menuMixedTestServer" xml:space="preserve">
<value>一鍵多執行緒測試延遲和速度 (Ctrl+E)</value> <value>一鍵多執行緒測試延遲和速度 (Ctrl+E)</value>
</data> </data>
@@ -1135,4 +1138,7 @@
<data name="menuOpenTheFileLocation" xml:space="preserve"> <data name="menuOpenTheFileLocation" xml:space="preserve">
<value>打開儲存所在的位置</value> <value>打開儲存所在的位置</value>
</data> </data>
<data name="menuProfileAutofitColumnWidth" xml:space="preserve">
<value>自動調整列寬</value>
</data>
</root> </root>

View File

@@ -20,9 +20,10 @@
"rules": [ "rules": [
{ {
"rule_set": [ "rule_set": [
"geosite-geolocation-!cn" "geosite-cn",
"geosite-geolocation-cn"
], ],
"server": "remote" "server": "local"
}, },
{ {
"rule_set": [ "rule_set": [
@@ -31,5 +32,5 @@
"server": "block" "server": "block"
} }
], ],
"final": "local" "final": "remote"
} }

View File

@@ -20,9 +20,10 @@
"rules": [ "rules": [
{ {
"rule_set": [ "rule_set": [
"geosite-geolocation-!cn" "geosite-cn",
"geosite-geolocation-cn"
], ],
"server": "remote" "server": "local"
}, },
{ {
"rule_set": [ "rule_set": [
@@ -31,5 +32,5 @@
"server": "block" "server": "block"
} }
], ],
"final": "local" "final": "remote"
} }

View File

@@ -18,10 +18,13 @@ namespace v2rayN.ViewModels
[Reactive] public bool useSystemHosts { get; set; } [Reactive] public bool useSystemHosts { get; set; }
[Reactive] public string domainStrategy4Freedom { get; set; } [Reactive] public string domainStrategy4Freedom { get; set; }
[Reactive] public string domainDNSAddress { get; set; }
[Reactive] public string normalDNS { get; set; } [Reactive] public string normalDNS { get; set; }
[Reactive] public string domainStrategy4Freedom2 { get; set; }
[Reactive] public string domainDNSAddress2 { get; set; }
[Reactive] public string normalDNS2 { get; set; } [Reactive] public string normalDNS2 { get; set; }
[Reactive] public string tunDNS2 { get; set; } [Reactive] public string tunDNS2 { get; set; }
[Reactive] public string domainStrategy4Freedom2 { get; set; }
public ReactiveCommand<Unit, Unit> SaveCmd { get; } public ReactiveCommand<Unit, Unit> SaveCmd { get; }
public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCmd { get; } public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCmd { get; }
@@ -36,12 +39,14 @@ namespace v2rayN.ViewModels
var item = LazyConfig.Instance.GetDNSItem(ECoreType.Xray); var item = LazyConfig.Instance.GetDNSItem(ECoreType.Xray);
useSystemHosts = item.useSystemHosts; useSystemHosts = item.useSystemHosts;
domainStrategy4Freedom = item?.domainStrategy4Freedom ?? string.Empty; domainStrategy4Freedom = item?.domainStrategy4Freedom ?? string.Empty;
domainDNSAddress = item?.domainDNSAddress ?? string.Empty;
normalDNS = item?.normalDNS ?? string.Empty; normalDNS = item?.normalDNS ?? string.Empty;
var item2 = LazyConfig.Instance.GetDNSItem(ECoreType.sing_box); var item2 = LazyConfig.Instance.GetDNSItem(ECoreType.sing_box);
domainStrategy4Freedom2 = item2?.domainStrategy4Freedom ?? string.Empty;
domainDNSAddress2 = item2?.domainDNSAddress ?? string.Empty;
normalDNS2 = item2?.normalDNS ?? string.Empty; normalDNS2 = item2?.normalDNS ?? string.Empty;
tunDNS2 = item2?.tunDNS ?? string.Empty; tunDNS2 = item2?.tunDNS ?? string.Empty;
domainStrategy4Freedom2 = item2?.domainStrategy4Freedom ?? string.Empty;
SaveCmd = ReactiveCommand.Create(() => SaveCmd = ReactiveCommand.Create(() =>
{ {
@@ -100,14 +105,16 @@ namespace v2rayN.ViewModels
var item = LazyConfig.Instance.GetDNSItem(ECoreType.Xray); var item = LazyConfig.Instance.GetDNSItem(ECoreType.Xray);
item.domainStrategy4Freedom = domainStrategy4Freedom; item.domainStrategy4Freedom = domainStrategy4Freedom;
item.domainDNSAddress = domainDNSAddress;
item.useSystemHosts = useSystemHosts; item.useSystemHosts = useSystemHosts;
item.normalDNS = normalDNS; item.normalDNS = normalDNS;
ConfigHandler.SaveDNSItems(_config, item); ConfigHandler.SaveDNSItems(_config, item);
var item2 = LazyConfig.Instance.GetDNSItem(ECoreType.sing_box); var item2 = LazyConfig.Instance.GetDNSItem(ECoreType.sing_box);
item2.normalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(normalDNS2));
item2.tunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(tunDNS2));
item2.domainStrategy4Freedom = domainStrategy4Freedom2; item2.domainStrategy4Freedom = domainStrategy4Freedom2;
item2.domainDNSAddress = domainDNSAddress2;
item2.normalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(normalDNS2));
item2.tunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(tunDNS2));;
ConfigHandler.SaveDNSItems(_config, item2); ConfigHandler.SaveDNSItems(_config, item2);
_noticeHandler?.Enqueue(ResUI.OperationSuccess); _noticeHandler?.Enqueue(ResUI.OperationSuccess);

View File

@@ -1,7 +1,4 @@
using DynamicData;
using DynamicData.Binding; using DynamicData.Binding;
using MaterialDesignColors;
using MaterialDesignColors.ColorManipulation;
using MaterialDesignThemes.Wpf; using MaterialDesignThemes.Wpf;
using ReactiveUI; using ReactiveUI;
using ReactiveUI.Fody.Helpers; using ReactiveUI.Fody.Helpers;
@@ -30,7 +27,6 @@ namespace v2rayN.ViewModels
private CoreHandler _coreHandler; private CoreHandler _coreHandler;
private static Config _config; private static Config _config;
private NoticeHandler? _noticeHandler; private NoticeHandler? _noticeHandler;
private readonly PaletteHelper _paletteHelper = new();
private Action<EViewAction> _updateView; private Action<EViewAction> _updateView;
private bool _showInTaskbar; private bool _showInTaskbar;
@@ -165,24 +161,6 @@ namespace v2rayN.ViewModels
[Reactive] [Reactive]
public bool EnableTun { get; set; } public bool EnableTun { get; set; }
[Reactive]
public bool ColorModeDark { get; set; }
private IObservableCollection<Swatch> _swatches = new ObservableCollectionExtended<Swatch>();
public IObservableCollection<Swatch> Swatches => _swatches;
[Reactive]
public Swatch SelectedSwatch { get; set; }
[Reactive]
public int CurrentFontSize { get; set; }
[Reactive]
public bool FollowSystemTheme { get; set; }
[Reactive]
public string CurrentLanguage { get; set; }
[Reactive] [Reactive]
public bool ShowClashUI { get; set; } public bool ShowClashUI { get; set; }
@@ -219,8 +197,6 @@ namespace v2rayN.ViewModels
} }
Init(); Init();
BindingUI();
RestoreUI();
#region WhenAnyValue && ReactiveCommand #region WhenAnyValue && ReactiveCommand
@@ -234,7 +210,7 @@ namespace v2rayN.ViewModels
y => y != null && !y.Text.IsNullOrEmpty()) y => y != null && !y.Text.IsNullOrEmpty())
.Subscribe(c => ServerSelectedChanged(c)); .Subscribe(c => ServerSelectedChanged(c));
SystemProxySelected = (int)_config.sysProxyType; SystemProxySelected = (int)_config.systemProxyItem.sysProxyType;
this.WhenAnyValue( this.WhenAnyValue(
x => x.SystemProxySelected, x => x.SystemProxySelected,
y => y >= 0) y => y >= 0)
@@ -429,7 +405,7 @@ namespace v2rayN.ViewModels
//RefreshServers(); //RefreshServers();
Reload(); Reload();
ChangeSystemProxyStatus(_config.sysProxyType, true); ChangeSystemProxyStatus(_config.systemProxyItem.sysProxyType, true);
} }
private void OnProgramStarted(object state, bool timeout) private void OnProgramStarted(object state, bool timeout)
@@ -824,33 +800,6 @@ namespace v2rayN.ViewModels
catch { } catch { }
} }
//private void ImportOldGuiConfig()
//{
// if (UI.OpenFileDialog(out string fileName,
// "guiNConfig|*.json|All|*.*") != true)
// {
// return;
// }
// if (Utils.IsNullOrEmpty(fileName))
// {
// return;
// }
// var ret = ConfigHandler.ImportOldGuiConfig(_config, fileName);
// if (ret == 0)
// {
// RefreshRoutingsMenu();
// InitSubscriptionView();
// RefreshServers();
// Reload();
// _noticeHandler?.Enqueue(ResUI.OperationSuccess);
// }
// else
// {
// _noticeHandler?.Enqueue(ResUI.OperationFailed);
// }
//}
#endregion Setting #endregion Setting
#region CheckUpdate #region CheckUpdate
@@ -936,7 +885,7 @@ namespace v2rayN.ViewModels
//ConfigHandler.SaveConfig(_config, false); //ConfigHandler.SaveConfig(_config, false);
ChangeSystemProxyStatus(_config.sysProxyType, false); ChangeSystemProxyStatus(_config.systemProxyItem.sysProxyType, false);
}); });
} }
@@ -955,21 +904,21 @@ namespace v2rayN.ViewModels
public void SetListenerType(ESysProxyType type) public void SetListenerType(ESysProxyType type)
{ {
if (_config.sysProxyType == type) if (_config.systemProxyItem.sysProxyType == type)
{ {
return; return;
} }
_config.sysProxyType = type; _config.systemProxyItem.sysProxyType = type;
ChangeSystemProxyStatus(type, true); ChangeSystemProxyStatus(type, true);
SystemProxySelected = (int)_config.sysProxyType; SystemProxySelected = (int)_config.systemProxyItem.sysProxyType;
ConfigHandler.SaveConfig(_config, false); ConfigHandler.SaveConfig(_config, false);
} }
private void ChangeSystemProxyStatus(ESysProxyType type, bool blChange) private void ChangeSystemProxyStatus(ESysProxyType type, bool blChange)
{ {
SysProxyHandle.UpdateSysProxy(_config, _config.tunModeItem.enableTun ? true : false); SysProxyHandle.UpdateSysProxy(_config, _config.tunModeItem.enableTun ? true : false);
_noticeHandler?.SendMessage($"{ResUI.TipChangeSystemProxy} - {_config.sysProxyType.ToString()}", true); _noticeHandler?.SendMessage($"{ResUI.TipChangeSystemProxy} - {_config.systemProxyItem.sysProxyType.ToString()}", true);
Application.Current?.Dispatcher.Invoke((Action)(() => Application.Current?.Dispatcher.Invoke((Action)(() =>
{ {
@@ -1046,7 +995,7 @@ namespace v2rayN.ViewModels
{ {
return; return;
} }
if (_config.sysProxyType == (ESysProxyType)SystemProxySelected) if (_config.systemProxyItem.sysProxyType == (ESysProxyType)SystemProxySelected)
{ {
return; return;
} }
@@ -1078,7 +1027,6 @@ namespace v2rayN.ViewModels
var bl = blShow ?? !_showInTaskbar; var bl = blShow ?? !_showInTaskbar;
if (bl) if (bl)
{ {
//Application.Current.MainWindow.ShowInTaskbar = true;
Application.Current.MainWindow.Show(); Application.Current.MainWindow.Show();
if (Application.Current.MainWindow.WindowState == WindowState.Minimized) if (Application.Current.MainWindow.WindowState == WindowState.Minimized)
{ {
@@ -1090,140 +1038,17 @@ namespace v2rayN.ViewModels
else else
{ {
Application.Current.MainWindow.Hide(); Application.Current.MainWindow.Hide();
//Application.Current.MainWindow.ShowInTaskbar = false;
//IntPtr windowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
//Utile.RegWriteValue(Global.MyRegPath, Utile.WindowHwndKey, Convert.ToString((long)windowHandle));
} }
_showInTaskbar = bl; _showInTaskbar = bl;
_config.uiItem.showInTaskbar = _showInTaskbar; _config.uiItem.showInTaskbar = _showInTaskbar;
} }
private void RestoreUI()
{
if (FollowSystemTheme)
{
ModifyTheme(!Utils.IsLightTheme());
}
else
{
ModifyTheme(_config.uiItem.colorModeDark);
}
if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty())
{
var swatch = new SwatchesProvider().Swatches.FirstOrDefault(t => t.Name == _config.uiItem.colorPrimaryName);
if (swatch != null
&& swatch.ExemplarHue != null
&& swatch.ExemplarHue?.Color != null)
{
ChangePrimaryColor(swatch.ExemplarHue.Color);
}
}
}
private void BindingUI()
{
ColorModeDark = _config.uiItem.colorModeDark;
FollowSystemTheme = _config.uiItem.followSystemTheme;
_swatches.AddRange(new SwatchesProvider().Swatches);
if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty())
{
SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.uiItem.colorPrimaryName);
}
CurrentFontSize = _config.uiItem.currentFontSize;
CurrentLanguage = _config.uiItem.currentLanguage;
this.WhenAnyValue(
x => x.ColorModeDark,
y => y == true)
.Subscribe(c =>
{
if (_config.uiItem.colorModeDark != ColorModeDark)
{
_config.uiItem.colorModeDark = ColorModeDark;
ModifyTheme(ColorModeDark);
ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(x => x.FollowSystemTheme,
y => y == true)
.Subscribe(c =>
{
if (_config.uiItem.followSystemTheme != FollowSystemTheme)
{
_config.uiItem.followSystemTheme = FollowSystemTheme;
ConfigHandler.SaveConfig(_config);
if (FollowSystemTheme)
{
ModifyTheme(!Utils.IsLightTheme());
}
else
{
ModifyTheme(ColorModeDark);
}
}
});
this.WhenAnyValue(
x => x.SelectedSwatch,
y => y != null && !y.Name.IsNullOrEmpty())
.Subscribe(c =>
{
if (SelectedSwatch == null
|| SelectedSwatch.Name.IsNullOrEmpty()
|| SelectedSwatch.ExemplarHue == null
|| SelectedSwatch.ExemplarHue?.Color == null)
{
return;
}
if (_config.uiItem.colorPrimaryName != SelectedSwatch?.Name)
{
_config.uiItem.colorPrimaryName = SelectedSwatch?.Name;
ChangePrimaryColor(SelectedSwatch.ExemplarHue.Color);
ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(
x => x.CurrentFontSize,
y => y > 0)
.Subscribe(c =>
{
if (CurrentFontSize >= Global.MinFontSize)
{
_config.uiItem.currentFontSize = CurrentFontSize;
double size = (long)CurrentFontSize;
Application.Current.Resources["StdFontSize"] = size;
Application.Current.Resources["StdFontSize1"] = size + 1;
Application.Current.Resources["StdFontSize2"] = size + 2;
Application.Current.Resources["StdFontSizeMsg"] = size - 1;
Application.Current.Resources["StdFontSize-1"] = size - 1;
ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(
x => x.CurrentLanguage,
y => y != null && !y.IsNullOrEmpty())
.Subscribe(c =>
{
if (!Utils.IsNullOrEmpty(CurrentLanguage))
{
_config.uiItem.currentLanguage = CurrentLanguage;
Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage);
ConfigHandler.SaveConfig(_config);
}
});
}
public void InboundDisplayStaus() public void InboundDisplayStaus()
{ {
StringBuilder sb = new(); StringBuilder sb = new();
sb.Append($"[{EInboundProtocol.socks}:{LazyConfig.Instance.GetLocalPort(EInboundProtocol.socks)}]"); sb.Append($"[{EInboundProtocol.socks}:{LazyConfig.Instance.GetLocalPort(EInboundProtocol.socks)}]");
sb.Append(" | "); sb.Append(" | ");
//if (_config.sysProxyType == ESysProxyType.ForcedChange) //if (_config.systemProxyItem.sysProxyType == ESysProxyType.ForcedChange)
//{ //{
// sb.Append($"[{Global.InboundHttp}({ResUI.SystemProxy}):{LazyConfig.Instance.GetLocalPort(Global.InboundHttp)}]"); // sb.Append($"[{Global.InboundHttp}({ResUI.SystemProxy}):{LazyConfig.Instance.GetLocalPort(Global.InboundHttp)}]");
//} //}
@@ -1254,27 +1079,6 @@ namespace v2rayN.ViewModels
} }
} }
public void ModifyTheme(bool isDarkTheme)
{
var theme = _paletteHelper.GetTheme();
theme.SetBaseTheme(isDarkTheme ? BaseTheme.Dark : BaseTheme.Light);
_paletteHelper.SetTheme(theme);
Utils.SetDarkBorder(Application.Current.MainWindow, isDarkTheme);
}
public void ChangePrimaryColor(System.Windows.Media.Color color)
{
var theme = _paletteHelper.GetTheme();
theme.PrimaryLight = new ColorPair(color.Lighten());
theme.PrimaryMid = new ColorPair(color);
theme.PrimaryDark = new ColorPair(color.Darken());
_paletteHelper.SetTheme(theme);
}
private void AutoHideStartup() private void AutoHideStartup()
{ {
if (_config.uiItem.autoHideStartup) if (_config.uiItem.autoHideStartup)

View File

@@ -80,6 +80,7 @@ namespace v2rayN.ViewModels
#region System proxy #region System proxy
[Reactive] public bool notProxyLocalAddress { get; set; }
[Reactive] public string systemProxyAdvancedProtocol { get; set; } [Reactive] public string systemProxyAdvancedProtocol { get; set; }
[Reactive] public string systemProxyExceptions { get; set; } [Reactive] public string systemProxyExceptions { get; set; }
@@ -178,8 +179,9 @@ namespace v2rayN.ViewModels
#region System proxy #region System proxy
systemProxyAdvancedProtocol = _config.systemProxyAdvancedProtocol; notProxyLocalAddress = _config.systemProxyItem.notProxyLocalAddress;
systemProxyExceptions = _config.systemProxyExceptions; systemProxyAdvancedProtocol = _config.systemProxyItem.systemProxyAdvancedProtocol;
systemProxyExceptions = _config.systemProxyItem.systemProxyExceptions;
#endregion System proxy #endregion System proxy
@@ -266,7 +268,8 @@ namespace v2rayN.ViewModels
var needReboot = (EnableStatistics != _config.guiItem.enableStatistics var needReboot = (EnableStatistics != _config.guiItem.enableStatistics
|| EnableDragDropSort != _config.uiItem.enableDragDropSort || EnableDragDropSort != _config.uiItem.enableDragDropSort
|| EnableHWA != _config.guiItem.enableHWA || EnableHWA != _config.guiItem.enableHWA
|| CurrentFontFamily != _config.uiItem.currentFontFamily); || CurrentFontFamily != _config.uiItem.currentFontFamily
|| MainGirdOrientation != (int)_config.uiItem.mainGirdOrientation);
//if (Utile.IsNullOrEmpty(Kcpmtu.ToString()) || !Utile.IsNumeric(Kcpmtu.ToString()) //if (Utile.IsNullOrEmpty(Kcpmtu.ToString()) || !Utile.IsNumeric(Kcpmtu.ToString())
// || Utile.IsNullOrEmpty(Kcptti.ToString()) || !Utile.IsNumeric(Kcptti.ToString()) // || Utile.IsNullOrEmpty(Kcptti.ToString()) || !Utile.IsNumeric(Kcptti.ToString())
@@ -338,8 +341,9 @@ namespace v2rayN.ViewModels
_config.uiItem.mainGirdOrientation = (EGirdOrientation)MainGirdOrientation; _config.uiItem.mainGirdOrientation = (EGirdOrientation)MainGirdOrientation;
//systemProxy //systemProxy
_config.systemProxyExceptions = systemProxyExceptions; _config.systemProxyItem.systemProxyExceptions = systemProxyExceptions;
_config.systemProxyAdvancedProtocol = systemProxyAdvancedProtocol; _config.systemProxyItem.notProxyLocalAddress = notProxyLocalAddress;
_config.systemProxyItem.systemProxyAdvancedProtocol = systemProxyAdvancedProtocol;
//tun mode //tun mode
_config.tunModeItem.strictRoute = TunStrictRoute; _config.tunModeItem.strictRoute = TunStrictRoute;

View File

@@ -0,0 +1,193 @@
using DynamicData;
using DynamicData.Binding;
using MaterialDesignColors;
using MaterialDesignColors.ColorManipulation;
using MaterialDesignThemes.Wpf;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
using System.Reactive.Linq;
using System.Windows;
using v2rayN.Handler;
using v2rayN.Models;
using v2rayN.Resx;
namespace v2rayN.ViewModels
{
public class ThemeSettingViewModel : ReactiveObject
{
private static Config _config;
private NoticeHandler? _noticeHandler;
private readonly PaletteHelper _paletteHelper = new();
[Reactive]
public bool ColorModeDark { get; set; }
private IObservableCollection<Swatch> _swatches = new ObservableCollectionExtended<Swatch>();
public IObservableCollection<Swatch> Swatches => _swatches;
[Reactive]
public Swatch SelectedSwatch { get; set; }
[Reactive]
public int CurrentFontSize { get; set; }
[Reactive]
public bool FollowSystemTheme { get; set; }
[Reactive]
public string CurrentLanguage { get; set; }
public ThemeSettingViewModel()
{
_config = LazyConfig.Instance.GetConfig();
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
MainFormHandler.Instance.RegisterSystemColorSet(_config, Application.Current.MainWindow, (bool bl) => { ModifyTheme(bl); });
BindingUI();
RestoreUI();
}
private void RestoreUI()
{
if (FollowSystemTheme)
{
ModifyTheme(!Utils.IsLightTheme());
}
else
{
ModifyTheme(_config.uiItem.colorModeDark);
}
if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty())
{
var swatch = new SwatchesProvider().Swatches.FirstOrDefault(t => t.Name == _config.uiItem.colorPrimaryName);
if (swatch != null
&& swatch.ExemplarHue != null
&& swatch.ExemplarHue?.Color != null)
{
ChangePrimaryColor(swatch.ExemplarHue.Color);
}
}
}
private void BindingUI()
{
ColorModeDark = _config.uiItem.colorModeDark;
FollowSystemTheme = _config.uiItem.followSystemTheme;
_swatches.AddRange(new SwatchesProvider().Swatches);
if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty())
{
SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.uiItem.colorPrimaryName);
}
CurrentFontSize = _config.uiItem.currentFontSize;
CurrentLanguage = _config.uiItem.currentLanguage;
this.WhenAnyValue(
x => x.ColorModeDark,
y => y == true)
.Subscribe(c =>
{
if (_config.uiItem.colorModeDark != ColorModeDark)
{
_config.uiItem.colorModeDark = ColorModeDark;
ModifyTheme(ColorModeDark);
ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(x => x.FollowSystemTheme,
y => y == true)
.Subscribe(c =>
{
if (_config.uiItem.followSystemTheme != FollowSystemTheme)
{
_config.uiItem.followSystemTheme = FollowSystemTheme;
ConfigHandler.SaveConfig(_config);
if (FollowSystemTheme)
{
ModifyTheme(!Utils.IsLightTheme());
}
else
{
ModifyTheme(ColorModeDark);
}
}
});
this.WhenAnyValue(
x => x.SelectedSwatch,
y => y != null && !y.Name.IsNullOrEmpty())
.Subscribe(c =>
{
if (SelectedSwatch == null
|| SelectedSwatch.Name.IsNullOrEmpty()
|| SelectedSwatch.ExemplarHue == null
|| SelectedSwatch.ExemplarHue?.Color == null)
{
return;
}
if (_config.uiItem.colorPrimaryName != SelectedSwatch?.Name)
{
_config.uiItem.colorPrimaryName = SelectedSwatch?.Name;
ChangePrimaryColor(SelectedSwatch.ExemplarHue.Color);
ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(
x => x.CurrentFontSize,
y => y > 0)
.Subscribe(c =>
{
if (CurrentFontSize >= Global.MinFontSize)
{
_config.uiItem.currentFontSize = CurrentFontSize;
double size = (long)CurrentFontSize;
Application.Current.Resources["StdFontSize"] = size;
Application.Current.Resources["StdFontSize1"] = size + 1;
Application.Current.Resources["StdFontSize2"] = size + 2;
Application.Current.Resources["StdFontSizeMsg"] = size - 1;
Application.Current.Resources["StdFontSize-1"] = size - 1;
ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(
x => x.CurrentLanguage,
y => y != null && !y.IsNullOrEmpty())
.Subscribe(c =>
{
if (!Utils.IsNullOrEmpty(CurrentLanguage) && _config.uiItem.currentLanguage != CurrentLanguage)
{
_config.uiItem.currentLanguage = CurrentLanguage;
Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage);
ConfigHandler.SaveConfig(_config);
_noticeHandler?.Enqueue(ResUI.NeedRebootTips);
}
});
}
public void ModifyTheme(bool isDarkTheme)
{
var theme = _paletteHelper.GetTheme();
theme.SetBaseTheme(isDarkTheme ? BaseTheme.Dark : BaseTheme.Light);
_paletteHelper.SetTheme(theme);
Utils.SetDarkBorder(Application.Current.MainWindow, isDarkTheme);
}
public void ChangePrimaryColor(System.Windows.Media.Color color)
{
var theme = _paletteHelper.GetTheme();
theme.PrimaryLight = new ColorPair(color.Lighten());
theme.PrimaryMid = new ColorPair(color);
theme.PrimaryDark = new ColorPair(color.Darken());
_paletteHelper.SetTheme(theme);
}
}
}

View File

@@ -1,11 +1,11 @@
<reactiveui:ReactiveUserControl <reactiveui:ReactiveUserControl
x:Class="v2rayN.Views.ClashConnectionsView" x:Class="v2rayN.Views.ClashConnectionsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:reactiveui="http://reactiveui.net"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:v2rayN.Resx" xmlns:resx="clr-namespace:v2rayN.Resx"
xmlns:vms="clr-namespace:v2rayN.ViewModels" xmlns:vms="clr-namespace:v2rayN.ViewModels"
d:DesignHeight="450" d:DesignHeight="450"
@@ -40,10 +40,11 @@
<Button <Button
x:Name="btnConnectionCloseAll" x:Name="btnConnectionCloseAll"
Width="30" Width="24"
Height="30" Height="24"
Margin="8,0" Margin="8,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"> Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuConnectionCloseAll}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Close" /> <materialDesign:PackIcon VerticalAlignment="Center" Kind="Close" />
</Button> </Button>

View File

@@ -1,12 +1,12 @@
<reactiveui:ReactiveUserControl <reactiveui:ReactiveUserControl
x:Class="v2rayN.Views.ClashProxiesView" x:Class="v2rayN.Views.ClashProxiesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:reactiveui="http://reactiveui.net"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="clr-namespace:v2rayN.Converters" 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:v2rayN.Resx" xmlns:resx="clr-namespace:v2rayN.Resx"
xmlns:vms="clr-namespace:v2rayN.ViewModels" xmlns:vms="clr-namespace:v2rayN.ViewModels"
d:DesignHeight="450" d:DesignHeight="450"
@@ -58,19 +58,21 @@
<Button <Button
x:Name="menuProxiesReload" x:Name="menuProxiesReload"
Width="30" Width="24"
Height="30" Height="24"
Margin="8,0" Margin="8,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"> Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuProxiesReload}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Reload" /> <materialDesign:PackIcon VerticalAlignment="Center" Kind="Reload" />
</Button> </Button>
<Button <Button
x:Name="menuProxiesDelaytest" x:Name="menuProxiesDelaytest"
Width="30" Width="24"
Height="30" Height="24"
Margin="8,0" Margin="8,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"> Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuProxiesDelaytest}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="LightningBolt" /> <materialDesign:PackIcon VerticalAlignment="Center" Kind="LightningBolt" />
</Button> </Button>

View File

@@ -49,33 +49,6 @@
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}"> <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}">
<DockPanel Margin="{StaticResource SettingItemMargin}"> <DockPanel Margin="{StaticResource SettingItemMargin}">
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" />
<ComboBox
x:Name="cmbdomainStrategy4Freedom"
Width="200"
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
</StackPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" />
<ToggleButton
x:Name="togUseSystemHosts"
Grid.Row="5"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock <TextBlock
Margin="{StaticResource SettingItemMargin}" Margin="{StaticResource SettingItemMargin}"
@@ -83,7 +56,7 @@
Style="{StaticResource ToolbarTextBlock}" Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" /> Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" />
<TextBlock <TextBlock
Margin="8,0,0,0" Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center" VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"> Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkDnsObjectDoc_Click"> <Hyperlink Click="linkDnsObjectDoc_Click">
@@ -93,12 +66,53 @@
</TextBlock> </TextBlock>
<Button <Button
x:Name="btnImportDefConfig4V2ray" x:Name="btnImportDefConfig4V2ray"
Margin="8,0,0,0" Margin="{StaticResource SettingItemMargin}"
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
Cursor="Hand" Cursor="Hand"
Style="{StaticResource DefButton}" /> Style="{StaticResource DefButton}" />
</StackPanel> </StackPanel>
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" />
<ToggleButton
x:Name="togUseSystemHosts"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" />
<ComboBox
x:Name="cmbdomainStrategy4Freedom"
Width="150"
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
<ComboBox
x:Name="cmbdomainDNSAddress"
Width="150"
Margin="{StaticResource SettingItemMargin}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
</StackPanel>
</WrapPanel>
<TextBox <TextBox
x:Name="txtnormalDNS" x:Name="txtnormalDNS"
Margin="{StaticResource SettingItemMargin}" Margin="{StaticResource SettingItemMargin}"
@@ -116,7 +130,7 @@
<DockPanel Margin="{StaticResource SettingItemMargin}"> <DockPanel Margin="{StaticResource SettingItemMargin}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock <TextBlock
Margin="8,0,0,0" Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center" VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"> Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkDnsSingboxObjectDoc_Click"> <Hyperlink Click="linkDnsSingboxObjectDoc_Click">
@@ -126,13 +140,14 @@
</TextBlock> </TextBlock>
<Button <Button
x:Name="btnImportDefConfig4Singbox" x:Name="btnImportDefConfig4Singbox"
Margin="8,0,0,0" Margin="{StaticResource SettingItemMargin}"
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
Cursor="Hand" Cursor="Hand"
Style="{StaticResource DefButton}" /> Style="{StaticResource DefButton}" />
</StackPanel> </StackPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<TextBlock <TextBlock
Margin="{StaticResource SettingItemMargin}" Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center" VerticalAlignment="Center"
@@ -140,11 +155,26 @@
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" /> Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" />
<ComboBox <ComboBox
x:Name="cmbdomainStrategy4Out" x:Name="cmbdomainStrategy4Out"
Width="200" Width="150"
Margin="{StaticResource SettingItemMargin}" Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource DefComboBox}" /> Style="{StaticResource DefComboBox}" />
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
<ComboBox
x:Name="cmbdomainDNSAddress2"
Width="150"
Margin="{StaticResource SettingItemMargin}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
</StackPanel>
</WrapPanel>
<Grid Margin="{StaticResource SettingItemMargin}"> <Grid Margin="{StaticResource SettingItemMargin}">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" />

View File

@@ -28,13 +28,24 @@ namespace v2rayN.Views
{ {
cmbdomainStrategy4Out.Items.Add(it); cmbdomainStrategy4Out.Items.Add(it);
}); });
Global.DomainDNSAddress.ForEach(it =>
{
cmbdomainDNSAddress.Items.Add(it);
});
Global.SingboxDomainDNSAddress.ForEach(it =>
{
cmbdomainDNSAddress2.Items.Add(it);
});
this.WhenActivated(disposables => this.WhenActivated(disposables =>
{ {
this.Bind(ViewModel, vm => vm.useSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.useSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.domainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.domainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.domainDNSAddress, v => v.cmbdomainDNSAddress.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.normalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.normalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.domainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.domainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.domainDNSAddress2, v => v.cmbdomainDNSAddress2.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.normalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.normalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.tunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.tunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables);

View File

@@ -301,88 +301,7 @@
HorizontalAlignment="Right" HorizontalAlignment="Right"
StaysOpen="True" StaysOpen="True"
Style="{StaticResource MaterialDesignToolForegroundPopupBox}"> Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
<StackPanel Margin="8"> <ContentControl x:Name="pbTheme" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsColorMode}" />
<ToggleButton
x:Name="togDarkMode"
Grid.Row="0"
Grid.Column="1"
Margin="8" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsFollowSystemTheme}" />
<ToggleButton
x:Name="followSystemTheme"
Grid.Row="1"
Grid.Column="1"
Margin="8" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsColor}" />
<ComboBox
x:Name="cmbSwatches"
Grid.Row="2"
Grid.Column="1"
Width="100"
Margin="8"
DisplayMemberPath="Name"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsFontSize}" />
<ComboBox
x:Name="cmbCurrentFontSize"
Grid.Row="3"
Grid.Column="1"
Width="100"
Margin="8"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsLanguage}" />
<ComboBox
x:Name="cmbCurrentLanguage"
Grid.Row="4"
Grid.Column="1"
Width="100"
Margin="8"
materialDesign:HintAssist.Hint="Language"
Style="{StaticResource DefComboBox}" />
</Grid>
</StackPanel>
</materialDesign:PopupBox> </materialDesign:PopupBox>
</ToolBar> </ToolBar>
</ToolBarTray> </ToolBarTray>
@@ -495,18 +414,122 @@
<TabControl <TabControl
x:Name="tabMain1" x:Name="tabMain1"
Grid.Row="2" Grid.Row="2"
HorizontalContentAlignment="Left"> materialDesign:NavigationRailAssist.ShowSelectionBackground="True"
<TabItem x:Name="tabMsgView1" Header="{x:Static resx:ResUI.MsgInformationTitle}" /> Style="{StaticResource MaterialDesignNavigationRailTabControl}"
<TabItem x:Name="tabClashProxies1" Header="{x:Static resx:ResUI.TbProxies}" /> TabStripPlacement="Left">
<TabItem x:Name="tabClashConnections1" Header="{x:Static resx:ResUI.TbConnections}" /> <TabItem x:Name="tabMsgView1">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="MessageTextOutline" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.MsgInformationTitle}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashProxies1">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="ArrowDecisionOutline" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbProxies}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashConnections1">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="LanConnect" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbConnections}" />
</StackPanel>
</TabItem.Header>
</TabItem>
</TabControl> </TabControl>
</Grid> </Grid>
<Grid x:Name="gridMain2" Visibility="Collapsed"> <Grid x:Name="gridMain2" Visibility="Collapsed">
<TabControl x:Name="tabMain2" HorizontalContentAlignment="Left"> <TabControl
<TabItem x:Name="tabProfiles2" Header="{x:Static resx:ResUI.menuServers}" /> x:Name="tabMain2"
<TabItem x:Name="tabMsgView2" Header="{x:Static resx:ResUI.MsgInformationTitle}" /> materialDesign:NavigationRailAssist.ShowSelectionBackground="True"
<TabItem x:Name="tabClashProxies2" Header="{x:Static resx:ResUI.TbProxies}" /> Style="{StaticResource MaterialDesignNavigationRailTabControl}"
<TabItem x:Name="tabClashConnections2" Header="{x:Static resx:ResUI.TbConnections}" /> TabStripPlacement="Left">
<TabItem x:Name="tabProfiles2">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="Server" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.menuServers}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabMsgView2">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="MessageTextOutline" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.MsgInformationTitle}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashProxies2">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="ArrowDecisionOutline" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbProxies}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashConnections2">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="LanConnect" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbConnections}" />
</StackPanel>
</TabItem.Header>
</TabItem>
</TabControl> </TabControl>
</Grid> </Grid>
<materialDesign:Snackbar x:Name="MainSnackbar" MessageQueue="{materialDesign:MessageQueue}" /> <materialDesign:Snackbar x:Name="MainSnackbar" MessageQueue="{materialDesign:MessageQueue}" />

View File

@@ -1,4 +1,5 @@
using ReactiveUI; using MaterialDesignThemes.Wpf;
using ReactiveUI;
using Splat; using Splat;
using System.ComponentModel; using System.ComponentModel;
using System.Reactive.Disposables; using System.Reactive.Disposables;
@@ -32,16 +33,6 @@ namespace v2rayN.Views
ViewModel = new MainWindowViewModel(MainSnackbar.MessageQueue, null); ViewModel = new MainWindowViewModel(MainSnackbar.MessageQueue, null);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel)); Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
for (int i = Global.MinFontSize; i <= Global.MinFontSize + 8; i++)
{
cmbCurrentFontSize.Items.Add(i.ToString());
}
Global.Languages.ForEach(it =>
{
cmbCurrentLanguage.Items.Add(it);
});
this.WhenActivated(disposables => this.WhenActivated(disposables =>
{ {
//servers //servers
@@ -130,14 +121,6 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SelectedRouting, v => v.cmbRoutings2.SelectedItem).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedRouting, v => v.cmbRoutings2.SelectedItem).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.BlRouting, v => v.cmbRoutings2.Visibility).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.BlRouting, v => v.cmbRoutings2.Visibility).DisposeWith(disposables);
//UI
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.followSystemTheme.IsChecked).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables);
if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal) if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal)
{ {
gridMain.Visibility = Visibility.Visible; gridMain.Visibility = Visibility.Visible;
@@ -169,8 +152,6 @@ namespace v2rayN.Views
RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;
} }
MainFormHandler.Instance.RegisterSystemColorSet(_config, this, (bool bl) => { ViewModel?.ModifyTheme(bl); });
if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal) if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal)
{ {
tabProfiles.Content ??= new ProfilesView(); tabProfiles.Content ??= new ProfilesView();
@@ -192,6 +173,7 @@ namespace v2rayN.Views
tabClashProxies2.Content ??= new ClashProxiesView(); tabClashProxies2.Content ??= new ClashProxiesView();
tabClashConnections2.Content ??= new ClashConnectionsView(); tabClashConnections2.Content ??= new ClashConnectionsView();
} }
pbTheme.Content ??= new ThemeSettingView();
RestoreUI(); RestoreUI();
AddHelpMenuItem(); AddHelpMenuItem();

View File

@@ -27,20 +27,22 @@
TextBoxBase.TextChanged="cmbMsgFilter_TextChanged" /> TextBoxBase.TextChanged="cmbMsgFilter_TextChanged" />
<Button <Button
x:Name="btnCopy" x:Name="btnCopy"
Width="30" Width="24"
Height="30" Height="24"
Margin="8,0" Margin="8,0"
Click="menuMsgViewCopyAll_Click" Click="menuMsgViewCopyAll_Click"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"> Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuMsgViewCopyAll}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="ContentCopy" /> <materialDesign:PackIcon VerticalAlignment="Center" Kind="ContentCopy" />
</Button> </Button>
<Button <Button
x:Name="btnClear" x:Name="btnClear"
Width="30" Width="24"
Height="30" Height="24"
Margin="8,0" Margin="8,0"
Click="menuMsgViewClear_Click" Click="menuMsgViewClear_Click"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"> Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuMsgViewClear}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Delete" /> <materialDesign:PackIcon VerticalAlignment="Center" Kind="Delete" />
</Button> </Button>
<TextBlock <TextBlock

View File

@@ -853,20 +853,32 @@
<TabItem Header="{x:Static resx:ResUI.TbSettingsSystemproxy}"> <TabItem Header="{x:Static resx:ResUI.TbSettingsSystemproxy}">
<DockPanel Margin="{StaticResource SettingItemMargin}"> <DockPanel Margin="{StaticResource SettingItemMargin}">
<StackPanel DockPanel.Dock="Bottom" Orientation="Vertical"> <StackPanel DockPanel.Dock="Bottom" Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsNotProxyLocalAddress}" />
<ToggleButton
x:Name="tognotProxyLocalAddress"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock <TextBlock
Grid.Row="3"
Margin="{StaticResource SettingItemMargin}" Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center" VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}" Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsAdvancedProtocol}" /> Text="{x:Static resx:ResUI.TbSettingsAdvancedProtocol}" />
<ComboBox <ComboBox
x:Name="cmbsystemProxyAdvancedProtocol" x:Name="cmbsystemProxyAdvancedProtocol"
Grid.Row="4" MinWidth="400"
MinWidth="200"
Margin="{StaticResource SettingItemMargin}" Margin="{StaticResource SettingItemMargin}"
materialDesign:HintAssist.Hint="Protocol" materialDesign:HintAssist.Hint="Protocol"
Style="{StaticResource DefComboBox}" /> Style="{StaticResource DefComboBox}" />
</StackPanel> </StackPanel>
</StackPanel>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"

View File

@@ -150,6 +150,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.notProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.systemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.systemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);

View File

@@ -39,7 +39,8 @@
Width="30" Width="30"
Height="30" Height="30"
Margin="4,0" Margin="4,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"> Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuSubEdit}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Edit" /> <materialDesign:PackIcon VerticalAlignment="Center" Kind="Edit" />
</Button> </Button>
<Button <Button
@@ -47,7 +48,8 @@
Width="30" Width="30"
Height="30" Height="30"
Margin="4,0" Margin="4,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"> Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuSubAdd}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Plus" /> <materialDesign:PackIcon VerticalAlignment="Center" Kind="Plus" />
</Button> </Button>
@@ -56,7 +58,8 @@
Width="30" Width="30"
Height="30" Height="30"
Margin="20,0" Margin="20,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"> Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuProfileAutofitColumnWidth}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="ArrowSplitVertical" /> <materialDesign:PackIcon VerticalAlignment="Center" Kind="ArrowSplitVertical" />
</Button> </Button>
<TextBox <TextBox

View File

@@ -0,0 +1,97 @@
<reactiveui:ReactiveUserControl
x:Class="v2rayN.Views.ThemeSettingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:v2rayN.Resx"
xmlns:vms="clr-namespace:v2rayN.ViewModels"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="vms:ThemeSettingViewModel"
mc:Ignorable="d">
<StackPanel Margin="8">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsColorMode}" />
<ToggleButton
x:Name="togDarkMode"
Grid.Row="0"
Grid.Column="1"
Margin="8" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsFollowSystemTheme}" />
<ToggleButton
x:Name="followSystemTheme"
Grid.Row="1"
Grid.Column="1"
Margin="8" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsColor}" />
<ComboBox
x:Name="cmbSwatches"
Grid.Row="2"
Grid.Column="1"
Width="100"
Margin="8"
DisplayMemberPath="Name"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsFontSize}" />
<ComboBox
x:Name="cmbCurrentFontSize"
Grid.Row="3"
Grid.Column="1"
Width="100"
Margin="8"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsLanguage}" />
<ComboBox
x:Name="cmbCurrentLanguage"
Grid.Row="4"
Grid.Column="1"
Width="100"
Margin="8"
Style="{StaticResource DefComboBox}" />
</Grid>
</StackPanel>
</reactiveui:ReactiveUserControl>

View File

@@ -0,0 +1,41 @@
using ReactiveUI;
using Splat;
using System.Reactive.Disposables;
using System.Windows.Input;
using v2rayN.Handler;
using v2rayN.ViewModels;
namespace v2rayN.Views
{
/// <summary>
/// ThemeSettingView.xaml
/// </summary>
public partial class ThemeSettingView
{
public ThemeSettingView()
{
InitializeComponent();
ViewModel = new ThemeSettingViewModel();
for (int i = Global.MinFontSize; i <= Global.MinFontSize + 8; i++)
{
cmbCurrentFontSize.Items.Add(i.ToString());
}
Global.Languages.ForEach(it =>
{
cmbCurrentLanguage.Items.Add(it);
});
this.WhenActivated(disposables =>
{
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.followSystemTheme.IsChecked).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables);
});
}
}
}

View File

@@ -10,7 +10,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<ApplicationIcon>v2rayN.ico</ApplicationIcon> <ApplicationIcon>v2rayN.ico</ApplicationIcon>
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright> <Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
<FileVersion>6.52</FileVersion> <FileVersion>6.55</FileVersion>
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
</PropertyGroup> </PropertyGroup>
@@ -26,7 +26,7 @@
<PackageReference Include="ReactiveUI.Validation" Version="4.0.9" /> <PackageReference Include="ReactiveUI.Validation" Version="4.0.9" />
<PackageReference Include="ReactiveUI.WPF" Version="20.1.1" /> <PackageReference Include="ReactiveUI.WPF" Version="20.1.1" />
<PackageReference Include="Splat.NLog" Version="15.1.1" /> <PackageReference Include="Splat.NLog" Version="15.1.1" />
<PackageReference Include="YamlDotNet" Version="15.3.0" /> <PackageReference Include="YamlDotNet" Version="16.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>