Compare commits

...

6 commits

Author SHA1 Message Date
2dust
91af50f99a Optimize code ,add IsGroupType extension. Adjust EConfigType
Some checks failed
release Linux / build (Release) (push) Has been cancelled
release macOS / build (Release) (push) Has been cancelled
release Windows desktop (Avalonia UI) / build (Release) (push) Has been cancelled
release Windows / build (Release) (push) Has been cancelled
2025-10-08 17:13:54 +08:00
2dust
a559586e71 Code clean 2025-10-08 15:48:51 +08:00
2dust
929520775d Bug fix 2025-10-08 15:48:45 +08:00
2dust
4eaf31bbf8 Fix
https://github.com/2dust/v2rayN/issues/8092
2025-10-08 14:36:47 +08:00
2dust
1607525539 Optimize the ruletype UI 2025-10-08 14:12:16 +08:00
DHR60
31b5b4ca0c
Add rule type selection to routing rules (#8007)
* Add rule type selection to routing rules

* Use enum

---------

Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
2025-10-08 10:40:26 +08:00
40 changed files with 285 additions and 117 deletions

View file

@ -84,4 +84,14 @@ public static class Extension
{ {
return source.Concat(new[] { string.Empty }).ToList(); return source.Concat(new[] { string.Empty }).ToList();
} }
public static bool IsGroupType(this EConfigType configType)
{
return configType is EConfigType.PolicyGroup or EConfigType.ProxyChain;
}
public static bool IsComplexType(this EConfigType configType)
{
return configType is EConfigType.Custom or EConfigType.PolicyGroup or EConfigType.ProxyChain;
}
} }

View file

@ -13,8 +13,6 @@ public enum EConfigType
WireGuard = 9, WireGuard = 9,
HTTP = 10, HTTP = 10,
Anytls = 11, Anytls = 11,
PolicyGroup = 101,
Group = 1000, ProxyChain = 102,
PolicyGroup = 1001,
ProxyChain = 1002,
} }

View file

@ -0,0 +1,8 @@
namespace ServiceLib.Enums;
public enum ERuleType
{
ALL = 0,
Routing = 1,
DNS = 2,
}

View file

@ -316,6 +316,8 @@ public class Global
EConfigType.HTTP, EConfigType.HTTP,
]; ];
public static readonly HashSet<EConfigType> SingboxOnlyConfigType = SingboxSupportConfigType.Except(XraySupportConfigType).ToHashSet();
public static readonly List<string> DomainStrategies = public static readonly List<string> DomainStrategies =
[ [
AsIs, AsIs,

View file

@ -357,7 +357,7 @@ public static class ConfigHandler
{ {
} }
} }
else if (profileItem.ConfigType > EConfigType.Group) else if (profileItem.ConfigType.IsGroupType())
{ {
var profileGroupItem = await AppManager.Instance.GetProfileGroupItem(it.IndexId); var profileGroupItem = await AppManager.Instance.GetProfileGroupItem(it.IndexId);
await AddGroupServerCommon(config, profileItem, profileGroupItem, true); await AddGroupServerCommon(config, profileItem, profileGroupItem, true);
@ -1255,7 +1255,7 @@ public static class ConfigHandler
if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun) if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun)
{ {
var tun2SocksAddress = node.Address; var tun2SocksAddress = node.Address;
if (node.ConfigType > EConfigType.Group) if (node.ConfigType.IsGroupType())
{ {
var lstAddresses = (await ProfileGroupItemManager.GetAllChildDomainAddresses(node.IndexId)).ToList(); var lstAddresses = (await ProfileGroupItemManager.GetAllChildDomainAddresses(node.IndexId)).ToList();
if (lstAddresses.Count > 0) if (lstAddresses.Count > 0)

View file

@ -77,7 +77,6 @@ public class ActionPrecheckManager(Config config)
return errors; return errors;
} }
switch (item.ConfigType) switch (item.ConfigType)
{ {
case EConfigType.VMess: case EConfigType.VMess:
@ -113,7 +112,7 @@ public class ActionPrecheckManager(Config config)
} }
} }
if (item.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (item.ConfigType.IsGroupType())
{ {
ProfileGroupItemManager.Instance.TryGet(item.IndexId, out var group); ProfileGroupItemManager.Instance.TryGet(item.IndexId, out var group);
if (group is null || group.ChildItems.IsNullOrEmpty()) if (group is null || group.ChildItems.IsNullOrEmpty())

View file

@ -95,7 +95,7 @@ public class CoreManager
public async Task<ProcessService?> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds) public async Task<ProcessService?> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
{ {
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls) ? ECoreType.sing_box : ECoreType.Xray; var coreType = selecteds.Any(t => Global.SingboxOnlyConfigType.Contains(t.ConfigType)) ? ECoreType.sing_box : ECoreType.Xray;
var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false)); var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));
var configPath = Utils.GetBinConfigPath(fileName); var configPath = Utils.GetBinConfigPath(fileName);
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType); var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);

View file

@ -269,7 +269,7 @@ public class ProfileGroupItemManager
{ {
childAddresses.Add(childNode.Address); childAddresses.Add(childNode.Address);
} }
else if (childNode.ConfigType > EConfigType.Group) else if (childNode.ConfigType.IsGroupType())
{ {
var subAddresses = await GetAllChildDomainAddresses(childNode.IndexId); var subAddresses = await GetAllChildDomainAddresses(childNode.IndexId);
foreach (var addr in subAddresses) foreach (var addr in subAddresses)

View file

@ -66,7 +66,7 @@ public class ProfileItem : ReactiveObject
public bool IsComplex() public bool IsComplex()
{ {
return ConfigType is EConfigType.Custom or > EConfigType.Group; return ConfigType.IsComplexType();
} }
public bool IsValid() public bool IsValid()

View file

@ -15,4 +15,5 @@ public class RulesItem
public List<string>? Process { get; set; } public List<string>? Process { get; set; }
public bool Enabled { get; set; } = true; public bool Enabled { get; set; } = true;
public string? Remarks { get; set; } public string? Remarks { get; set; }
public ERuleType? RuleType { get; set; }
} }

View file

@ -7,4 +7,5 @@ public class RulesItemModel : RulesItem
public string Ips { get; set; } public string Ips { get; set; }
public string Domains { get; set; } public string Domains { get; set; }
public string Protocols { get; set; } public string Protocols { get; set; }
public string RuleTypeName { get; set; }
} }

View file

@ -3156,6 +3156,24 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Rule Type 的本地化字符串。
/// </summary>
public static string TbRuleType {
get {
return ResourceManager.GetString("TbRuleType", resourceCulture);
}
}
/// <summary>
/// 查找类似 You can set separate rules for Routing and DNS, or select &quot;ALL&quot; to apply to both 的本地化字符串。
/// </summary>
public static string TbRuleTypeTips {
get {
return ResourceManager.GetString("TbRuleTypeTips", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Bootstrap DNS (sing-box) 的本地化字符串。 /// 查找类似 Bootstrap DNS (sing-box) 的本地化字符串。
/// </summary> /// </summary>

View file

@ -1596,4 +1596,10 @@
<data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve">
<value>If the system does not have a tray function, please do not enable it</value> <value>If the system does not have a tray function, please do not enable it</value>
</data> </data>
<data name="TbRuleType" xml:space="preserve">
<value>Rule Type</value>
</data>
<data name="TbRuleTypeTips" xml:space="preserve">
<value>You can set separate rules for Routing and DNS, or select "ALL" to apply to both</value>
</data>
</root> </root>

View file

@ -1596,4 +1596,10 @@
<data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve">
<value>If the system does not have a tray function, please do not enable it</value> <value>If the system does not have a tray function, please do not enable it</value>
</data> </data>
<data name="TbRuleTypeTips" xml:space="preserve">
<value>You can set separate rules for Routing and DNS, or select "ALL" to apply to both</value>
</data>
<data name="TbRuleType" xml:space="preserve">
<value>Rule Type</value>
</data>
</root> </root>

View file

@ -1596,4 +1596,10 @@
<data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve">
<value>If the system does not have a tray function, please do not enable it</value> <value>If the system does not have a tray function, please do not enable it</value>
</data> </data>
<data name="TbRuleTypeTips" xml:space="preserve">
<value>You can set separate rules for Routing and DNS, or select "ALL" to apply to both</value>
</data>
<data name="TbRuleType" xml:space="preserve">
<value>Rule Type</value>
</data>
</root> </root>

View file

@ -1596,4 +1596,10 @@
<data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve">
<value>If the system does not have a tray function, please do not enable it</value> <value>If the system does not have a tray function, please do not enable it</value>
</data> </data>
<data name="TbRuleTypeTips" xml:space="preserve">
<value>You can set separate rules for Routing and DNS, or select "ALL" to apply to both</value>
</data>
<data name="TbRuleType" xml:space="preserve">
<value>Rule Type</value>
</data>
</root> </root>

View file

@ -1593,4 +1593,10 @@
<data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve">
<value>如果系统没有托盘功能,请不要开启</value> <value>如果系统没有托盘功能,请不要开启</value>
</data> </data>
<data name="TbRuleType" xml:space="preserve">
<value>规则类型</value>
</data>
<data name="TbRuleTypeTips" xml:space="preserve">
<value>可对 Routing 和 DNS 单独设定规则ALL 则都生效</value>
</data>
</root> </root>

View file

@ -1593,4 +1593,10 @@
<data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenCloseTip" xml:space="preserve">
<value>如果系統沒有托盤功能,請不要開啟</value> <value>如果系統沒有托盤功能,請不要開啟</value>
</data> </data>
<data name="TbRuleType" xml:space="preserve">
<value>规则类型</value>
</data>
<data name="TbRuleTypeTips" xml:space="preserve">
<value>可对 Routing 和 DNS 单独设定规则ALL 则都生效</value>
</data>
</root> </root>

View file

@ -1,5 +1,6 @@
using System.Net; using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using ServiceLib.Common;
namespace ServiceLib.Services.CoreConfig; namespace ServiceLib.Services.CoreConfig;
@ -29,12 +30,13 @@ public partial class CoreConfigSingboxService(Config config)
ret.Msg = ResUI.InitialConfiguration; ret.Msg = ResUI.InitialConfiguration;
if (node?.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (node.ConfigType.IsGroupType())
{ {
switch (node.ConfigType) switch (node.ConfigType)
{ {
case EConfigType.PolicyGroup: case EConfigType.PolicyGroup:
return await GenerateClientMultipleLoadConfig(node); return await GenerateClientMultipleLoadConfig(node);
case EConfigType.ProxyChain: case EConfigType.ProxyChain:
return await GenerateClientChainConfig(node); return await GenerateClientChainConfig(node);
} }

View file

@ -253,6 +253,11 @@ public partial class CoreConfigSingboxService
continue; continue;
} }
if (item.RuleType == ERuleType.Routing)
{
continue;
}
var rule = new Rule4Sbox(); var rule = new Rule4Sbox();
var validDomains = item.Domain.Count(it => ParseV2Domain(it, rule)); var validDomains = item.Domain.Count(it => ParseV2Domain(it, rule));
if (validDomains <= 0) if (validDomains <= 0)

View file

@ -208,7 +208,7 @@ public partial class CoreConfigSingboxService
{ {
try try
{ {
if (node.ConfigType is not (EConfigType.PolicyGroup or EConfigType.ProxyChain)) if (!node.ConfigType.IsGroupType())
{ {
return -1; return -1;
} }
@ -236,9 +236,11 @@ public partial class CoreConfigSingboxService
} }
break; break;
case EConfigType.ProxyChain: case EConfigType.ProxyChain:
await GenChainOutboundsList(childProfiles, singboxConfig, baseTagName); await GenChainOutboundsList(childProfiles, singboxConfig, baseTagName);
break; break;
default: default:
break; break;
} }
@ -492,7 +494,7 @@ public partial class CoreConfigSingboxService
{ {
index++; index++;
if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (node.ConfigType.IsGroupType())
{ {
var (childProfiles, profileGroupItem) = await ProfileGroupItemManager.GetChildProfileItems(node.IndexId); var (childProfiles, profileGroupItem) = await ProfileGroupItemManager.GetChildProfileItems(node.IndexId);
if (childProfiles.Count <= 0) if (childProfiles.Count <= 0)
@ -667,7 +669,7 @@ public partial class CoreConfigSingboxService
var node = nodes[i]; var node = nodes[i];
if (node == null) if (node == null)
continue; continue;
if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (node.ConfigType.IsGroupType())
{ {
var (childProfiles, profileGroupItem) = await ProfileGroupItemManager.GetChildProfileItems(node.IndexId); var (childProfiles, profileGroupItem) = await ProfileGroupItemManager.GetChildProfileItems(node.IndexId);
if (childProfiles.Count <= 0) if (childProfiles.Count <= 0)

View file

@ -136,16 +136,24 @@ public partial class CoreConfigSingboxService
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet); var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
foreach (var item1 in rules ?? []) foreach (var item1 in rules ?? [])
{ {
if (item1.Enabled) if (!item1.Enabled)
{ {
continue;
}
if (item1.RuleType == ERuleType.DNS)
{
continue;
}
await GenRoutingUserRule(item1, singboxConfig); await GenRoutingUserRule(item1, singboxConfig);
if (item1.Ip != null && item1.Ip.Count > 0)
if (item1.Ip?.Count > 0)
{ {
ipRules.Add(item1); ipRules.Add(item1);
} }
} }
} }
}
if (_config.RoutingBasicItem.DomainStrategy == Global.IPIfNonMatch) if (_config.RoutingBasicItem.DomainStrategy == Global.IPIfNonMatch)
{ {
singboxConfig.route.rules.Add(resolveRule); singboxConfig.route.rules.Add(resolveRule);
@ -371,7 +379,7 @@ public partial class CoreConfigSingboxService
if (node == null if (node == null
|| (!Global.SingboxSupportConfigType.Contains(node.ConfigType) || (!Global.SingboxSupportConfigType.Contains(node.ConfigType)
&& node.ConfigType is not (EConfigType.PolicyGroup or EConfigType.ProxyChain))) && !node.ConfigType.IsGroupType()))
{ {
return Global.ProxyTag; return Global.ProxyTag;
} }
@ -383,7 +391,7 @@ public partial class CoreConfigSingboxService
return tag; return tag;
} }
if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (node.ConfigType.IsGroupType())
{ {
var ret = await GenGroupOutbound(node, singboxConfig, tag); var ret = await GenGroupOutbound(node, singboxConfig, tag);
if (ret == 0) if (ret == 0)

View file

@ -30,12 +30,13 @@ public partial class CoreConfigV2rayService(Config config)
ret.Msg = ResUI.InitialConfiguration; ret.Msg = ResUI.InitialConfiguration;
if (node?.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (node.ConfigType.IsGroupType())
{ {
switch (node.ConfigType) switch (node.ConfigType)
{ {
case EConfigType.PolicyGroup: case EConfigType.PolicyGroup:
return await GenerateClientMultipleLoadConfig(node); return await GenerateClientMultipleLoadConfig(node);
case EConfigType.ProxyChain: case EConfigType.ProxyChain:
return await GenerateClientChainConfig(node); return await GenerateClientChainConfig(node);
} }

View file

@ -142,6 +142,11 @@ public partial class CoreConfigV2rayService
continue; continue;
} }
if (item.RuleType == ERuleType.Routing)
{
continue;
}
foreach (var domain in item.Domain) foreach (var domain in item.Domain)
{ {
if (domain.StartsWith('#')) if (domain.StartsWith('#'))

View file

@ -484,7 +484,7 @@ public partial class CoreConfigV2rayService
{ {
try try
{ {
if (node.ConfigType is not (EConfigType.PolicyGroup or EConfigType.ProxyChain)) if (!node.ConfigType.IsGroupType())
{ {
return -1; return -1;
} }
@ -511,9 +511,11 @@ public partial class CoreConfigV2rayService
await GenOutboundsListWithChain(childProfiles, v2rayConfig, baseTagName); await GenOutboundsListWithChain(childProfiles, v2rayConfig, baseTagName);
} }
break; break;
case EConfigType.ProxyChain: case EConfigType.ProxyChain:
await GenChainOutboundsList(childProfiles, v2rayConfig, baseTagName); await GenChainOutboundsList(childProfiles, v2rayConfig, baseTagName);
break; break;
default: default:
break; break;
} }
@ -629,7 +631,7 @@ public partial class CoreConfigV2rayService
{ {
index++; index++;
if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (node.ConfigType.IsGroupType())
{ {
var (childProfiles, _) = await ProfileGroupItemManager.GetChildProfileItems(node.IndexId); var (childProfiles, _) = await ProfileGroupItemManager.GetChildProfileItems(node.IndexId);
if (childProfiles.Count <= 0) if (childProfiles.Count <= 0)
@ -780,7 +782,7 @@ public partial class CoreConfigV2rayService
var node = nodes[i]; var node = nodes[i];
if (node == null) if (node == null)
continue; continue;
if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (node.ConfigType.IsGroupType())
{ {
var (childProfiles, _) = await ProfileGroupItemManager.GetChildProfileItems(node.IndexId); var (childProfiles, _) = await ProfileGroupItemManager.GetChildProfileItems(node.IndexId);
if (childProfiles.Count <= 0) if (childProfiles.Count <= 0)

View file

@ -20,15 +20,22 @@ public partial class CoreConfigV2rayService
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet); var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
foreach (var item in rules) foreach (var item in rules)
{ {
if (item.Enabled) if (!item.Enabled)
{ {
continue;
}
if (item.RuleType == ERuleType.DNS)
{
continue;
}
var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item)); var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));
await GenRoutingUserRule(item2, v2rayConfig); await GenRoutingUserRule(item2, v2rayConfig);
} }
} }
} }
} }
}
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(_tag, ex); Logging.SaveLog(_tag, ex);
@ -128,7 +135,7 @@ public partial class CoreConfigV2rayService
if (node == null if (node == null
|| (!Global.XraySupportConfigType.Contains(node.ConfigType) || (!Global.XraySupportConfigType.Contains(node.ConfigType)
&& node.ConfigType is not (EConfigType.PolicyGroup or EConfigType.ProxyChain))) && !node.ConfigType.IsGroupType()))
{ {
return Global.ProxyTag; return Global.ProxyTag;
} }
@ -139,7 +146,7 @@ public partial class CoreConfigV2rayService
return tag; return tag;
} }
if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (node.ConfigType.IsGroupType())
{ {
var ret = await GenGroupOutbound(node, v2rayConfig, tag); var ret = await GenGroupOutbound(node, v2rayConfig, tag);
if (ret == 0) if (ret == 0)

View file

@ -64,7 +64,7 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
var lstSelected = new List<ServerTestItem>(); var lstSelected = new List<ServerTestItem>();
foreach (var it in selecteds) foreach (var it in selecteds)
{ {
if (it.ConfigType == EConfigType.Custom) if (it.ConfigType.IsComplexType())
{ {
continue; continue;
} }
@ -116,10 +116,6 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
List<Task> tasks = []; List<Task> tasks = [];
foreach (var it in selecteds) foreach (var it in selecteds)
{ {
if (it.ConfigType == EConfigType.Custom)
{
continue;
}
tasks.Add(Task.Run(async () => tasks.Add(Task.Run(async () =>
{ {
try try
@ -199,10 +195,6 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
{ {
continue; continue;
} }
if (it.ConfigType == EConfigType.Custom)
{
continue;
}
tasks.Add(Task.Run(async () => tasks.Add(Task.Run(async () =>
{ {
await DoRealPing(it); await DoRealPing(it);
@ -215,9 +207,12 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
Logging.SaveLog(_tag, ex); Logging.SaveLog(_tag, ex);
} }
finally finally
{
if (processService != null)
{ {
await processService?.StopAsync(); await processService?.StopAsync();
} }
}
return true; return true;
} }
@ -233,10 +228,6 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
await UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip); await UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
continue; continue;
} }
if (it.ConfigType == EConfigType.Custom)
{
continue;
}
await concurrencySemaphore.WaitAsync(); await concurrencySemaphore.WaitAsync();
tasks.Add(Task.Run(async () => tasks.Add(Task.Run(async () =>
@ -271,8 +262,11 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
Logging.SaveLog(_tag, ex); Logging.SaveLog(_tag, ex);
} }
finally finally
{
if (processService != null)
{ {
await processService?.StopAsync(); await processService?.StopAsync();
}
concurrencySemaphore.Release(); concurrencySemaphore.Release();
} }
})); }));
@ -345,7 +339,7 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
{ {
List<List<ServerTestItem>> lstTest = new(); List<List<ServerTestItem>> lstTest = new();
var lst1 = lstSelected.Where(t => Global.XraySupportConfigType.Contains(t.ConfigType)).ToList(); var lst1 = lstSelected.Where(t => Global.XraySupportConfigType.Contains(t.ConfigType)).ToList();
var lst2 = lstSelected.Where(t => Global.SingboxSupportConfigType.Contains(t.ConfigType) && !Global.XraySupportConfigType.Contains(t.ConfigType)).ToList(); var lst2 = lstSelected.Where(t => Global.SingboxOnlyConfigType.Contains(t.ConfigType)).ToList();
for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++) for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)
{ {

View file

@ -350,7 +350,7 @@ public class MainWindowViewModel : MyReactiveObject
{ {
ret = await _updateView?.Invoke(EViewAction.AddServer2Window, item); ret = await _updateView?.Invoke(EViewAction.AddServer2Window, item);
} }
else if (eConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) else if (eConfigType.IsGroupType())
{ {
ret = await _updateView?.Invoke(EViewAction.AddGroupServerWindow, item); ret = await _updateView?.Invoke(EViewAction.AddGroupServerWindow, item);
} }

View file

@ -510,7 +510,7 @@ public class ProfilesViewModel : MyReactiveObject
{ {
ret = await _updateView?.Invoke(EViewAction.AddServer2Window, item); ret = await _updateView?.Invoke(EViewAction.AddServer2Window, item);
} }
else if (eConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) else if (eConfigType.IsGroupType())
{ {
ret = await _updateView?.Invoke(EViewAction.AddGroupServerWindow, item); ret = await _updateView?.Invoke(EViewAction.AddGroupServerWindow, item);
} }

View file

@ -21,6 +21,9 @@ public class RoutingRuleDetailsViewModel : MyReactiveObject
[Reactive] [Reactive]
public string Process { get; set; } public string Process { get; set; }
[Reactive]
public string? RuleType { get; set; }
[Reactive] [Reactive]
public bool AutoSort { get; set; } public bool AutoSort { get; set; }
@ -51,6 +54,7 @@ public class RoutingRuleDetailsViewModel : MyReactiveObject
Domain = Utils.List2String(SelectedSource.Domain, true); Domain = Utils.List2String(SelectedSource.Domain, true);
IP = Utils.List2String(SelectedSource.Ip, true); IP = Utils.List2String(SelectedSource.Ip, true);
Process = Utils.List2String(SelectedSource.Process, true); Process = Utils.List2String(SelectedSource.Process, true);
RuleType = SelectedSource.RuleType?.ToString();
} }
private async Task SaveRulesAsync() private async Task SaveRulesAsync()
@ -73,6 +77,7 @@ public class RoutingRuleDetailsViewModel : MyReactiveObject
} }
SelectedSource.Protocol = ProtocolItems?.ToList(); SelectedSource.Protocol = ProtocolItems?.ToList();
SelectedSource.InboundTag = InboundTagItems?.ToList(); SelectedSource.InboundTag = InboundTagItems?.ToList();
SelectedSource.RuleType = RuleType.IsNullOrEmpty() ? null : (ERuleType)Enum.Parse(typeof(ERuleType), RuleType);
var hasRule = SelectedSource.Domain?.Count > 0 var hasRule = SelectedSource.Domain?.Count > 0
|| SelectedSource.Ip?.Count > 0 || SelectedSource.Ip?.Count > 0

View file

@ -107,13 +107,13 @@ public class RoutingRuleSettingViewModel : MyReactiveObject
var it = new RulesItemModel() var it = new RulesItemModel()
{ {
Id = item.Id, Id = item.Id,
RuleTypeName = item.RuleType?.ToString(),
OutboundTag = item.OutboundTag, OutboundTag = item.OutboundTag,
Port = item.Port, Port = item.Port,
Network = item.Network, Network = item.Network,
Protocols = Utils.List2String(item.Protocol), Protocols = Utils.List2String(item.Protocol),
InboundTags = Utils.List2String(item.InboundTag), InboundTags = Utils.List2String(item.InboundTag),
Domains = Utils.List2String(item.Domain), Domains = Utils.List2String((item.Domain ?? []).Concat(item.Ip ?? []).ToList()),
Ips = Utils.List2String(item.Ip),
Enabled = item.Enabled, Enabled = item.Enabled,
Remarks = item.Remarks, Remarks = item.Remarks,
}; };

View file

@ -40,6 +40,7 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
case EConfigType.PolicyGroup: case EConfigType.PolicyGroup:
this.Title = ResUI.TbConfigTypePolicyGroup; this.Title = ResUI.TbConfigTypePolicyGroup;
break; break;
case EConfigType.ProxyChain: case EConfigType.ProxyChain:
this.Title = ResUI.TbConfigTypeProxyChain; this.Title = ResUI.TbConfigTypeProxyChain;
gridPolicyGroup.IsVisible = false; gridPolicyGroup.IsVisible = false;
@ -115,18 +116,22 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
ViewModel?.MoveServer(EMove.Top); ViewModel?.MoveServer(EMove.Top);
e.Handled = true; e.Handled = true;
break; break;
case Key.U: case Key.U:
ViewModel?.MoveServer(EMove.Up); ViewModel?.MoveServer(EMove.Up);
e.Handled = true; e.Handled = true;
break; break;
case Key.D: case Key.D:
ViewModel?.MoveServer(EMove.Down); ViewModel?.MoveServer(EMove.Down);
e.Handled = true; e.Handled = true;
break; break;
case Key.B: case Key.B:
ViewModel?.MoveServer(EMove.Bottom); ViewModel?.MoveServer(EMove.Bottom);
e.Handled = true; e.Handled = true;
break; break;
case Key.Delete: case Key.Delete:
ViewModel?.ChildRemoveAsync(); ViewModel?.ChildRemoveAsync();
e.Handled = true; e.Handled = true;
@ -162,5 +167,4 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
ViewModel.SelectedChildren = lstChild.SelectedItems.Cast<ProfileItem>().ToList(); ViewModel.SelectedChildren = lstChild.SelectedItems.Cast<ProfileItem>().ToList();
} }
} }
} }

View file

@ -31,12 +31,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
_config = AppManager.Instance.Config; _config = AppManager.Instance.Config;
_manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.TopRight }; _manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.TopRight };
if (_config.UiItem.AutoHideStartup)
{
this.ShowActivated = false;
this.WindowState = WindowState.Minimized;
}
this.KeyDown += MainWindow_KeyDown; this.KeyDown += MainWindow_KeyDown;
menuSettingsSetUWP.Click += menuSettingsSetUWP_Click; menuSettingsSetUWP.Click += menuSettingsSetUWP_Click;
menuPromotion.Click += menuPromotion_Click; menuPromotion.Click += menuPromotion_Click;
@ -184,6 +178,11 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
} }
menuAddServerViaScan.IsVisible = false; menuAddServerViaScan.IsVisible = false;
if (_config.UiItem.AutoHideStartup)
{
this.WindowState = WindowState.Minimized;
}
AddHelpMenuItem(); AddHelpMenuItem();
} }

View file

@ -18,7 +18,7 @@
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
ColumnDefinitions="Auto,Auto,Auto" ColumnDefinitions="Auto,Auto,Auto"
DockPanel.Dock="Top" DockPanel.Dock="Top"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto"> RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"
Grid.Column="0" Grid.Column="0"
@ -32,29 +32,57 @@
Width="300" Width="300"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" /> HorizontalAlignment="Left" />
<ToggleSwitch <StackPanel
x:Name="togEnabled"
Grid.Row="0" Grid.Row="0"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Center"
Orientation="Horizontal">
<ToggleSwitch
x:Name="togEnabled"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
VerticalAlignment="Center" /> VerticalAlignment="Center" />
</StackPanel>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbRuleType}" />
<ComboBox
x:Name="cmbRuleType"
Grid.Row="1"
Grid.Column="1"
Width="300"
Margin="{StaticResource Margin4}"
MaxDropDownHeight="1000" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbRuleTypeTips}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="outboundTag" /> Text="outboundTag" />
<ComboBox <ComboBox
Name="cmbOutboundTag" Name="cmbOutboundTag"
Grid.Row="1" Grid.Row="2"
Grid.Column="1" Grid.Column="1"
Width="300" Width="300"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
IsEditable="True" /> IsEditable="True" />
<StackPanel <StackPanel
Grid.Row="1" Grid.Row="2"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -69,20 +97,20 @@
</StackPanel> </StackPanel>
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="3"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="port" /> Text="port" />
<TextBox <TextBox
x:Name="txtPort" x:Name="txtPort"
Grid.Row="2" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
Width="300" Width="300"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" /> HorizontalAlignment="Left" />
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="3"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -90,21 +118,21 @@
Text="{x:Static resx:ResUI.TbRuleMatchingTips}" /> Text="{x:Static resx:ResUI.TbRuleMatchingTips}" />
<TextBlock <TextBlock
Grid.Row="3" Grid.Row="4"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="protocol" /> Text="protocol" />
<ListBox <ListBox
x:Name="clbProtocol" x:Name="clbProtocol"
Grid.Row="3" Grid.Row="4"
Grid.Column="1" Grid.Column="1"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
SelectionMode="Multiple,Toggle" SelectionMode="Multiple,Toggle"
Theme="{DynamicResource CardCheckGroupListBox}" /> Theme="{DynamicResource CardCheckGroupListBox}" />
<TextBlock <TextBlock
Grid.Row="3" Grid.Row="4"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center"> VerticalAlignment="Center">
@ -114,20 +142,20 @@
</TextBlock> </TextBlock>
<TextBlock <TextBlock
Grid.Row="4" Grid.Row="5"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="inboundTag" /> Text="inboundTag" />
<ListBox <ListBox
x:Name="clbInboundTag" x:Name="clbInboundTag"
Grid.Row="4" Grid.Row="5"
Grid.Column="1" Grid.Column="1"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
SelectionMode="Multiple,Toggle" SelectionMode="Multiple,Toggle"
Theme="{DynamicResource CardCheckGroupListBox}" /> Theme="{DynamicResource CardCheckGroupListBox}" />
<TextBlock <TextBlock
Grid.Row="4" Grid.Row="5"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -135,20 +163,20 @@
Text="{x:Static resx:ResUI.TbRoutingInboundTagTips}" /> Text="{x:Static resx:ResUI.TbRoutingInboundTagTips}" />
<TextBlock <TextBlock
Grid.Row="5" Grid.Row="6"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="network" /> Text="network" />
<ComboBox <ComboBox
x:Name="cmbNetwork" x:Name="cmbNetwork"
Grid.Row="5" Grid.Row="6"
Grid.Column="1" Grid.Column="1"
Width="300" Width="300"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
MaxDropDownHeight="1000" /> MaxDropDownHeight="1000" />
<TextBlock <TextBlock
Grid.Row="5" Grid.Row="6"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"

View file

@ -28,6 +28,7 @@ public partial class RoutingRuleDetailsWindow : WindowBase<RoutingRuleDetailsVie
clbProtocol.ItemsSource = Global.RuleProtocols; clbProtocol.ItemsSource = Global.RuleProtocols;
clbInboundTag.ItemsSource = Global.InboundTags; clbInboundTag.ItemsSource = Global.InboundTags;
cmbNetwork.ItemsSource = Global.RuleNetworks; cmbNetwork.ItemsSource = Global.RuleNetworks;
cmbRuleType.ItemsSource = Utils.GetEnumNames<ERuleType>().AppendEmpty();
if (!rulesItem.Id.IsNullOrEmpty()) if (!rulesItem.Id.IsNullOrEmpty())
{ {
@ -53,6 +54,7 @@ public partial class RoutingRuleDetailsWindow : WindowBase<RoutingRuleDetailsVie
this.Bind(ViewModel, vm => vm.IP, v => v.txtIP.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.IP, v => v.txtIP.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Process, v => v.txtProcess.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.Process, v => v.txtProcess.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.AutoSort, v => v.chkAutoSort.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AutoSort, v => v.chkAutoSort.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RuleType, v => v.cmbRuleType.SelectedValue).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
}); });

View file

@ -209,7 +209,11 @@
Binding="{Binding Remarks}" Binding="{Binding Remarks}"
Header="{x:Static resx:ResUI.LvRemarks}" /> Header="{x:Static resx:ResUI.LvRemarks}" />
<DataGridTextColumn <DataGridTextColumn
Width="120" Width="100"
Binding="{Binding RuleTypeName}"
Header="{x:Static resx:ResUI.TbRuleType}" />
<DataGridTextColumn
Width="130"
Binding="{Binding OutboundTag}" Binding="{Binding OutboundTag}"
Header="outboundTag" /> Header="outboundTag" />
<DataGridTextColumn <DataGridTextColumn
@ -225,17 +229,13 @@
Binding="{Binding InboundTags}" Binding="{Binding InboundTags}"
Header="inboundTag" /> Header="inboundTag" />
<DataGridTextColumn <DataGridTextColumn
Width="90" Width="100"
Binding="{Binding Network}" Binding="{Binding Network}"
Header="network" /> Header="network" />
<DataGridTextColumn <DataGridTextColumn
Width="*" Width="*"
Binding="{Binding Domains}" Binding="{Binding Domains}"
Header="domain" /> Header="domain / ip" />
<DataGridTextColumn
Width="*"
Binding="{Binding Ips}"
Header="ip" />
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
</TabItem> </TabItem>

View file

@ -25,12 +25,6 @@ public partial class MainWindow
_config = AppManager.Instance.Config; _config = AppManager.Instance.Config;
ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false); ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
if (_config.UiItem.AutoHideStartup)
{
this.ShowActivated = false;
this.WindowState = WindowState.Minimized;
}
App.Current.SessionEnding += Current_SessionEnding; App.Current.SessionEnding += Current_SessionEnding;
this.Closing += MainWindow_Closing; this.Closing += MainWindow_Closing;
this.PreviewKeyDown += MainWindow_PreviewKeyDown; this.PreviewKeyDown += MainWindow_PreviewKeyDown;
@ -164,6 +158,10 @@ public partial class MainWindow
}); });
this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}"; this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
if (_config.UiItem.AutoHideStartup)
{
this.WindowState = WindowState.Minimized;
}
if (!_config.GuiItem.EnableHWA) if (!_config.GuiItem.EnableHWA)
{ {

View file

@ -26,6 +26,7 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@ -48,13 +49,19 @@
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" /> Style="{StaticResource DefTextBox}" />
<ToggleButton <StackPanel
x:Name="togEnabled"
Grid.Row="0" Grid.Row="0"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Center"
Orientation="Horizontal">
<ToggleButton
x:Name="togEnabled"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
VerticalAlignment="Center" /> VerticalAlignment="Center" />
</StackPanel>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@ -62,10 +69,34 @@
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}" Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRuleType}" />
<ComboBox
x:Name="cmbRuleType"
Grid.Row="1"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}"
MaxDropDownHeight="1000"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRuleTypeTips}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="outboundTag" /> Text="outboundTag" />
<ComboBox <ComboBox
x:Name="cmbOutboundTag" x:Name="cmbOutboundTag"
Grid.Row="1" Grid.Row="2"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
@ -73,7 +104,7 @@
MaxDropDownHeight="1000" MaxDropDownHeight="1000"
Style="{StaticResource DefComboBox}" /> Style="{StaticResource DefComboBox}" />
<StackPanel <StackPanel
Grid.Row="1" Grid.Row="2"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -92,7 +123,7 @@
</StackPanel> </StackPanel>
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="3"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
@ -100,14 +131,14 @@
Text="port" /> Text="port" />
<TextBox <TextBox
x:Name="txtPort" x:Name="txtPort"
Grid.Row="2" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" /> Style="{StaticResource DefTextBox}" />
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="3"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -116,7 +147,7 @@
Text="{x:Static resx:ResUI.TbRuleMatchingTips}" /> Text="{x:Static resx:ResUI.TbRuleMatchingTips}" />
<TextBlock <TextBlock
Grid.Row="3" Grid.Row="4"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
@ -124,14 +155,14 @@
Text="protocol" /> Text="protocol" />
<ListBox <ListBox
x:Name="clbProtocol" x:Name="clbProtocol"
Grid.Row="3" Grid.Row="4"
Grid.Column="1" Grid.Column="1"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
FontSize="{DynamicResource StdFontSize}" FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFilterChipPrimaryListBox}" /> Style="{StaticResource MaterialDesignFilterChipPrimaryListBox}" />
<TextBlock <TextBlock
Grid.Row="3" Grid.Row="4"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
@ -143,7 +174,7 @@
</TextBlock> </TextBlock>
<TextBlock <TextBlock
Grid.Row="4" Grid.Row="5"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
@ -151,13 +182,13 @@
Text="inboundTag" /> Text="inboundTag" />
<ListBox <ListBox
x:Name="clbInboundTag" x:Name="clbInboundTag"
Grid.Row="4" Grid.Row="5"
Grid.Column="1" Grid.Column="1"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
FontSize="{DynamicResource StdFontSize}" FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFilterChipPrimaryListBox}" /> Style="{StaticResource MaterialDesignFilterChipPrimaryListBox}" />
<TextBlock <TextBlock
Grid.Row="4" Grid.Row="5"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -166,7 +197,7 @@
Text="{x:Static resx:ResUI.TbRoutingInboundTagTips}" /> Text="{x:Static resx:ResUI.TbRoutingInboundTagTips}" />
<TextBlock <TextBlock
Grid.Row="5" Grid.Row="6"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
@ -174,7 +205,7 @@
Text="network" /> Text="network" />
<ComboBox <ComboBox
x:Name="cmbNetwork" x:Name="cmbNetwork"
Grid.Row="5" Grid.Row="6"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
@ -182,7 +213,7 @@
Style="{StaticResource DefComboBox}" /> Style="{StaticResource DefComboBox}" />
<TextBlock <TextBlock
Grid.Row="5" Grid.Row="6"
Grid.Column="2" Grid.Column="2"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" HorizontalAlignment="Left"

View file

@ -21,6 +21,7 @@ public partial class RoutingRuleDetailsWindow
clbProtocol.ItemsSource = Global.RuleProtocols; clbProtocol.ItemsSource = Global.RuleProtocols;
clbInboundTag.ItemsSource = Global.InboundTags; clbInboundTag.ItemsSource = Global.InboundTags;
cmbNetwork.ItemsSource = Global.RuleNetworks; cmbNetwork.ItemsSource = Global.RuleNetworks;
cmbRuleType.ItemsSource = Utils.GetEnumNames<ERuleType>().AppendEmpty();
if (!rulesItem.Id.IsNullOrEmpty()) if (!rulesItem.Id.IsNullOrEmpty())
{ {
@ -45,6 +46,7 @@ public partial class RoutingRuleDetailsWindow
this.Bind(ViewModel, vm => vm.IP, v => v.txtIP.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.IP, v => v.txtIP.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Process, v => v.txtProcess.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.Process, v => v.txtProcess.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.AutoSort, v => v.chkAutoSort.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AutoSort, v => v.chkAutoSort.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.RuleType, v => v.cmbRuleType.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
}); });

View file

@ -301,7 +301,11 @@
Binding="{Binding Remarks}" Binding="{Binding Remarks}"
Header="{x:Static resx:ResUI.LvRemarks}" /> Header="{x:Static resx:ResUI.LvRemarks}" />
<DataGridTextColumn <DataGridTextColumn
Width="120" Width="100"
Binding="{Binding RuleTypeName}"
Header="{x:Static resx:ResUI.TbRuleType}" />
<DataGridTextColumn
Width="130"
Binding="{Binding OutboundTag}" Binding="{Binding OutboundTag}"
Header="outboundTag" /> Header="outboundTag" />
<DataGridTextColumn <DataGridTextColumn
@ -317,17 +321,13 @@
Binding="{Binding InboundTags}" Binding="{Binding InboundTags}"
Header="inboundTag" /> Header="inboundTag" />
<DataGridTextColumn <DataGridTextColumn
Width="90" Width="100"
Binding="{Binding Network}" Binding="{Binding Network}"
Header="network" /> Header="network" />
<DataGridTextColumn <DataGridTextColumn
Width="*" Width="*"
Binding="{Binding Domains}" Binding="{Binding Domains}"
Header="domain" /> Header="domain / ip" />
<DataGridTextColumn
Width="*"
Binding="{Binding Ips}"
Header="ip" />
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
</TabItem> </TabItem>