Add Singbox Geo RuleSet setting

This commit is contained in:
GibMeMyPacket 2024-04-15 16:50:22 +00:00 committed by GibMeMyPacket
parent e0cea929ea
commit 24e7258534
16 changed files with 756 additions and 472 deletions

View file

@ -43,6 +43,7 @@ namespace v2rayN
public const string TunSingboxRulesFileName = "v2rayN.Sample.tun_singbox_rules"; public const string TunSingboxRulesFileName = "v2rayN.Sample.tun_singbox_rules";
public const string DNSV2rayNormalFileName = "v2rayN.Sample.dns_v2ray_normal"; public const string DNSV2rayNormalFileName = "v2rayN.Sample.dns_v2ray_normal";
public const string DNSSingboxNormalFileName = "v2rayN.Sample.dns_singbox_normal"; public const string DNSSingboxNormalFileName = "v2rayN.Sample.dns_singbox_normal";
public const string SingboxGeoRuleSetsFileName = "v2rayN.Sample.singbox_geo_rulesets";
public const string DefaultSecurity = "auto"; public const string DefaultSecurity = "auto";
public const string DefaultNetwork = "tcp"; public const string DefaultNetwork = "tcp";

View file

@ -1780,5 +1780,44 @@ namespace v2rayN.Handler
} }
#endregion DNS #endregion DNS
}
#region Sing Geo RuleSets
public static int InitBuiltinSingGeoRuleSets(Config config)
{
var item = LazyConfig.Instance.GetSingGeoRuleSets();
if (item is not null && item.rules != "")
{
return 0;
}
var item2 = new SingGeoRuleSet()
{
id = Utils.GetGUID(false),
remarks = "sing-box",
rules = Utils.GetEmbedText(Global.SingboxGeoRuleSetsFileName),
};
return SaveSingGeoRuleSet(config, item2);
}
public static int SaveSingGeoRuleSet(Config config, SingGeoRuleSet item)
{
if (Utils.IsNullOrEmpty(item.id))
{
item.id = Utils.GetGUID(false);
}
if (SQLiteHelper.Instance.Replace(item) > 0)
{
return 0;
}
else
{
return -1;
}
}
public static SingGeoRuleSet? GetDefaultSingGeoRuleSet(Config config)
{
return LazyConfig.Instance.GetSingGeoRuleSets();
}
#endregion
}
} }

View file

@ -1,4 +1,5 @@
using System.Net; using System.Globalization;
using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using v2rayN.Models; using v2rayN.Models;
using v2rayN.Resx; using v2rayN.Resx;
@ -56,6 +57,8 @@ namespace v2rayN.Handler
GenStatistic(singboxConfig); GenStatistic(singboxConfig);
GenGeoRuleSetFromJson(singboxConfig);
ConvertGeo2Ruleset(singboxConfig); ConvertGeo2Ruleset(singboxConfig);
msg = string.Format(ResUI.SuccessfulConfiguration, ""); msg = string.Format(ResUI.SuccessfulConfiguration, "");
@ -886,9 +889,20 @@ namespace v2rayN.Handler
} }
//Add ruleset srs //Add ruleset srs
singboxConfig.route.rule_set = []; if (singboxConfig.route.rule_set is null) singboxConfig.route.rule_set = new();
foreach (var item in new HashSet<string>(ruleSets)) foreach (var item in new HashSet<string>(ruleSets))
{ {
var exists = false;
foreach (var ruleSetItem in singboxConfig.route.rule_set)
{
if (ruleSetItem?.url?.EndsWith(item + ".srs", true, CultureInfo.InvariantCulture) ?? false)
{
exists = true;
break;
}
}
if (exists) continue;
singboxConfig.route.rule_set.Add(new() singboxConfig.route.rule_set.Add(new()
{ {
type = "remote", type = "remote",
@ -898,7 +912,27 @@ namespace v2rayN.Handler
download_detour = Global.ProxyTag download_detour = Global.ProxyTag
}); });
} }
return 0;
}
private int GenGeoRuleSetFromJson(SingboxConfig singboxConfig)
{
var gr = LazyConfig.Instance.GetSingGeoRuleSets();
if (gr == null) return -1;
var rules = gr.rules;
if (gr.rules.Length == 0) return -1;
var parsedRules = JsonUtils.Deserialize<List<Ruleset4Sbox>>(rules);
if (parsedRules is null) return -1;
// manipulate and set defaults
for (int i = 0; i < parsedRules.Count; i++)
{
if (string.IsNullOrEmpty(parsedRules[i].download_detour)) parsedRules[i].download_detour = "proxy";
if (string.IsNullOrEmpty(parsedRules[i].format)) parsedRules[i].format = "binary";
if (string.IsNullOrEmpty(parsedRules[i].type)) parsedRules[i].type = "remote";
}
if (singboxConfig.route.rule_set is null) singboxConfig.route.rule_set = new();
singboxConfig.route.rule_set.AddRange(parsedRules);
return 0; return 0;
} }

View file

@ -36,6 +36,7 @@ namespace v2rayN.Handler
SQLiteHelper.Instance.CreateTable<RoutingItem>(); SQLiteHelper.Instance.CreateTable<RoutingItem>();
SQLiteHelper.Instance.CreateTable<ProfileExItem>(); SQLiteHelper.Instance.CreateTable<ProfileExItem>();
SQLiteHelper.Instance.CreateTable<DNSItem>(); SQLiteHelper.Instance.CreateTable<DNSItem>();
SQLiteHelper.Instance.CreateTable<SingGeoRuleSet>();
} }
#region Config #region Config
@ -160,6 +161,11 @@ namespace v2rayN.Handler
return SQLiteHelper.Instance.Table<DNSItem>().FirstOrDefault(it => it.coreType == eCoreType); return SQLiteHelper.Instance.Table<DNSItem>().FirstOrDefault(it => it.coreType == eCoreType);
} }
public SingGeoRuleSet? GetSingGeoRuleSets()
{
return SQLiteHelper.Instance.Table<SingGeoRuleSet>().FirstOrDefault();
}
#endregion SqliteHelper #endregion SqliteHelper
#region Core Type #region Core Type

View file

@ -0,0 +1,15 @@
using SQLite;
namespace v2rayN.Models
{
[Serializable]
public class SingGeoRuleSet
{
[PrimaryKey]
public string id { get; set; }
public string remarks { get; set; }
public string rules { get; set; }
}
}

File diff suppressed because it is too large Load diff

View file

@ -1003,4 +1003,10 @@
<data name="TbSettingsEnableHWA" xml:space="preserve"> <data name="TbSettingsEnableHWA" xml:space="preserve">
<value>فعال‌سازی شتاب‌دهنده سخت‌افزاری (نیاز به راه‌اندازی مجدد)</value> <value>فعال‌سازی شتاب‌دهنده سخت‌افزاری (نیاز به راه‌اندازی مجدد)</value>
</data> </data>
<data name="TbRoutingTabRuleSet" xml:space="preserve">
<value>لیست مجموعه فایل های Geo برای Sing-box</value>
</data>
<data name="TbSettingSingGeoImportDefRuleSets" xml:space="preserve">
<value>برای وارد کردن مجموعه قوانین Geo کلیک کنید</value>
</data>
</root> </root>

View file

@ -1207,4 +1207,16 @@
<data name="TbSettingsEnableFragment" xml:space="preserve"> <data name="TbSettingsEnableFragment" xml:space="preserve">
<value>Enable fragment</value> <value>Enable fragment</value>
</data> </data>
<data name="TbRoutingTabRuleSet" xml:space="preserve">
<value>Sing-box Geo RuleSets</value>
</data>
<data name="TbSettingsSingGeoRuleSets" xml:space="preserve">
<value>Sing-box Geo RuleSet JSON (Array)</value>
</data>
<data name="TbSettingSingGeoImportDefRuleSets" xml:space="preserve">
<value>Click here to import default geo ruleset(s)</value>
</data>
<data name="TbSingGeoRuleSetDoc" xml:space="preserve">
<value>Please fill in RuleSet structure, click to view the document</value>
</data>
</root> </root>

View file

@ -1204,4 +1204,16 @@
<data name="TbSettingsEnableFragmentTips" xml:space="preserve"> <data name="TbSettingsEnableFragmentTips" xml:space="preserve">
<value>使用Xray且非Tun模式启用和分组前置代理冲突</value> <value>使用Xray且非Tun模式启用和分组前置代理冲突</value>
</data> </data>
<data name="TbRoutingTabRuleSet" xml:space="preserve">
<value>Sing-Box Geo规则集</value>
</data>
<data name="TbSettingsSingGeoRuleSets" xml:space="preserve">
<value>Sing-Box Geo Ruleset JSON数组</value>
</data>
<data name="TbSettingSingGeoImportDefRuleSets" xml:space="preserve">
<value>单击此处以导入默认地理规则集</value>
</data>
<data name="TbSingGeoRuleSetDoc" xml:space="preserve">
<value>请填写规则集结构,单击以查看文档</value>
</data>
</root> </root>

View file

@ -1177,4 +1177,16 @@
<data name="TbSettingsEnableFragmentTips" xml:space="preserve"> <data name="TbSettingsEnableFragmentTips" xml:space="preserve">
<value>使用Xray且非Tun模式啟用和分組前置代理衝突</value> <value>使用Xray且非Tun模式啟用和分組前置代理衝突</value>
</data> </data>
<data name="TbSingGeoRuleSetDoc" xml:space="preserve">
<value>請填寫規則集結構,單擊以查看文檔</value>
</data>
<data name="TbSettingsSingGeoRuleSets" xml:space="preserve">
<value>Sing-Box Geo Ruleset JSON數組</value>
</data>
<data name="TbRoutingTabRuleSet" xml:space="preserve">
<value>Sing-Box Geo規則集</value>
</data>
<data name="TbSettingSingGeoImportDefRuleSets" xml:space="preserve">
<value>單擊此處以導入默認地理規則集</value>
</data>
</root> </root>

View file

@ -0,0 +1,8 @@
[
{
"tag": "geosite-category-ads-all",
"type": "remote",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-category-ads-all.srs"
}
]

View file

@ -581,6 +581,7 @@ namespace v2rayN.ViewModels
{ {
ConfigHandler.InitBuiltinRouting(_config); ConfigHandler.InitBuiltinRouting(_config);
ConfigHandler.InitBuiltinDNS(_config); ConfigHandler.InitBuiltinDNS(_config);
ConfigHandler.InitBuiltinSingGeoRuleSets(_config);
_coreHandler = new CoreHandler(_config, UpdateHandler); _coreHandler = new CoreHandler(_config, UpdateHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => _coreHandler, typeof(CoreHandler)); Locator.CurrentMutable.RegisterLazySingleton(() => _coreHandler, typeof(CoreHandler));
@ -1389,6 +1390,7 @@ namespace v2rayN.ViewModels
if (ret == true) if (ret == true)
{ {
ConfigHandler.InitBuiltinRouting(_config); ConfigHandler.InitBuiltinRouting(_config);
ConfigHandler.InitBuiltinSingGeoRuleSets(_config);
RefreshRoutingsMenu(); RefreshRoutingsMenu();
//RefreshServers(); //RefreshServers();
Reload(); Reload();

View file

@ -62,11 +62,15 @@ namespace v2rayN.ViewModels
[Reactive] [Reactive]
public string BlockIP { get; set; } public string BlockIP { get; set; }
[Reactive]
public string SingGeoRuleSets { get; set; }
public ReactiveCommand<Unit, Unit> RoutingBasicImportRulesCmd { get; } public ReactiveCommand<Unit, Unit> RoutingBasicImportRulesCmd { get; }
public ReactiveCommand<Unit, Unit> RoutingAdvancedAddCmd { get; } public ReactiveCommand<Unit, Unit> RoutingAdvancedAddCmd { get; }
public ReactiveCommand<Unit, Unit> RoutingAdvancedRemoveCmd { get; } public ReactiveCommand<Unit, Unit> RoutingAdvancedRemoveCmd { get; }
public ReactiveCommand<Unit, Unit> RoutingAdvancedSetDefaultCmd { get; } public ReactiveCommand<Unit, Unit> RoutingAdvancedSetDefaultCmd { get; }
public ReactiveCommand<Unit, Unit> RoutingAdvancedImportRulesCmd { get; } public ReactiveCommand<Unit, Unit> RoutingAdvancedImportRulesCmd { get; }
public ReactiveCommand<Unit, Unit> RoutingImportSingGeoDefRuleSetsCmd { get; }
public ReactiveCommand<Unit, Unit> SaveCmd { get; } public ReactiveCommand<Unit, Unit> SaveCmd { get; }
public bool IsModified { get; set; } public bool IsModified { get; set; }
@ -81,6 +85,7 @@ namespace v2rayN.ViewModels
SelectedSource = new(); SelectedSource = new();
ConfigHandler.InitBuiltinRouting(_config); ConfigHandler.InitBuiltinRouting(_config);
ConfigHandler.InitBuiltinSingGeoRuleSets(_config);
enableRoutingAdvanced = _config.routingBasicItem.enableRoutingAdvanced; enableRoutingAdvanced = _config.routingBasicItem.enableRoutingAdvanced;
domainStrategy = _config.routingBasicItem.domainStrategy; domainStrategy = _config.routingBasicItem.domainStrategy;
@ -88,6 +93,8 @@ namespace v2rayN.ViewModels
domainStrategy4Singbox = _config.routingBasicItem.domainStrategy4Singbox; domainStrategy4Singbox = _config.routingBasicItem.domainStrategy4Singbox;
RefreshRoutingItems(); RefreshRoutingItems();
var geoRulesets = LazyConfig.Instance.GetSingGeoRuleSets();
if (geoRulesets != null) SingGeoRuleSets = geoRulesets.rules;
BindingLockedData(); BindingLockedData();
@ -121,6 +128,11 @@ namespace v2rayN.ViewModels
RoutingAdvancedImportRules(); RoutingAdvancedImportRules();
}); });
RoutingImportSingGeoDefRuleSetsCmd = ReactiveCommand.Create(() =>
{
SingGeoRuleSets = Utils.GetEmbedText(Global.SingboxGeoRuleSetsFileName);
});
SaveCmd = ReactiveCommand.Create(() => SaveCmd = ReactiveCommand.Create(() =>
{ {
SaveRouting(); SaveRouting();
@ -165,6 +177,13 @@ namespace v2rayN.ViewModels
ConfigHandler.SaveRoutingItem(_config, _lockedItem); ConfigHandler.SaveRoutingItem(_config, _lockedItem);
} }
var ruleSet = ConfigHandler.GetDefaultSingGeoRuleSet(_config);
if (ruleSet != null)
{
ruleSet.rules = SingGeoRuleSets;
ConfigHandler.SaveSingGeoRuleSet(_config, ruleSet);
}
} }
#endregion locked #endregion locked

View file

@ -155,44 +155,44 @@
<DockPanel> <DockPanel>
<TabControl x:Name="tabAdvanced"> <TabControl x:Name="tabAdvanced">
<TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbRoutingTabRuleList}"> <TabItem Header="{x:Static resx:ResUI.TbRoutingTabRuleList}">
<DataGrid <DataGrid
x:Name="lstRoutings" x:Name="lstRoutings"
Margin="2,0" Margin="2,0"
AutoGenerateColumns="False" AutoGenerateColumns="False"
BorderThickness="1" BorderThickness="1"
CanUserAddRows="False" CanUserAddRows="False"
CanUserResizeRows="False" CanUserResizeRows="False"
CanUserSortColumns="False" CanUserSortColumns="False"
EnableRowVirtualization="True" EnableRowVirtualization="True"
GridLinesVisibility="All" GridLinesVisibility="All"
HeadersVisibility="Column" HeadersVisibility="Column"
IsReadOnly="True" IsReadOnly="True"
Style="{StaticResource DefDataGrid}"> Style="{StaticResource DefDataGrid}">
<DataGrid.ContextMenu> <DataGrid.ContextMenu>
<ContextMenu Style="{StaticResource DefContextMenu}"> <ContextMenu Style="{StaticResource DefContextMenu}">
<MenuItem <MenuItem
x:Name="menuRoutingAdvancedAdd" x:Name="menuRoutingAdvancedAdd"
Height="{StaticResource MenuItemHeight}" Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRoutingAdvancedAdd}" /> Header="{x:Static resx:ResUI.menuRoutingAdvancedAdd}" />
<MenuItem <MenuItem
x:Name="menuRoutingAdvancedRemove" x:Name="menuRoutingAdvancedRemove"
Height="{StaticResource MenuItemHeight}" Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRoutingAdvancedRemove}" /> Header="{x:Static resx:ResUI.menuRoutingAdvancedRemove}" />
<MenuItem <MenuItem
x:Name="menuRoutingAdvancedSelectAll" x:Name="menuRoutingAdvancedSelectAll"
Height="{StaticResource MenuItemHeight}" Height="{StaticResource MenuItemHeight}"
Click="menuRoutingAdvancedSelectAll_Click" Click="menuRoutingAdvancedSelectAll_Click"
Header="{x:Static resx:ResUI.menuSelectAll}" /> Header="{x:Static resx:ResUI.menuSelectAll}" />
<MenuItem <MenuItem
x:Name="menuRoutingAdvancedSetDefault" x:Name="menuRoutingAdvancedSetDefault"
Height="{StaticResource MenuItemHeight}" Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRoutingAdvancedSetDefault}" /> Header="{x:Static resx:ResUI.menuRoutingAdvancedSetDefault}" />
<Separator /> <Separator />
<MenuItem <MenuItem
x:Name="menuRoutingAdvancedImportRules" x:Name="menuRoutingAdvancedImportRules"
Height="{StaticResource MenuItemHeight}" Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRoutingAdvancedImportRules}" /> Header="{x:Static resx:ResUI.menuRoutingAdvancedImportRules}" />
</ContextMenu> </ContextMenu>
</DataGrid.ContextMenu> </DataGrid.ContextMenu>
<DataGrid.Resources> <DataGrid.Resources>
@ -208,29 +208,64 @@
</DataGrid.Resources> </DataGrid.Resources>
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn <DataGridTextColumn
Width="250" Width="250"
Binding="{Binding remarks}" Binding="{Binding remarks}"
Header="{x:Static resx:ResUI.LvRemarks}" /> Header="{x:Static resx:ResUI.LvRemarks}" />
<DataGridTextColumn <DataGridTextColumn
Width="60" Width="60"
Binding="{Binding ruleNum}" Binding="{Binding ruleNum}"
Header="{x:Static resx:ResUI.LvCount}" /> Header="{x:Static resx:ResUI.LvCount}" />
<DataGridTextColumn <DataGridTextColumn
Width="60" Width="60"
Binding="{Binding sort}" Binding="{Binding sort}"
Header="{x:Static resx:ResUI.LvSort}" /> Header="{x:Static resx:ResUI.LvSort}" />
<DataGridTextColumn <DataGridTextColumn
Width="300" Width="300"
Binding="{Binding url}" Binding="{Binding url}"
Header="{x:Static resx:ResUI.LvUrl}" /> Header="{x:Static resx:ResUI.LvUrl}" />
<DataGridTextColumn <DataGridTextColumn
Width="300" Width="300"
Binding="{Binding customIcon}" Binding="{Binding customIcon}"
Header="{x:Static resx:ResUI.LvCustomIcon}" /> Header="{x:Static resx:ResUI.LvCustomIcon}" />
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
</TabItem> </TabItem>
</TabControl>
<TabItem Header="{x:Static resx:ResUI.TbRoutingTabRuleSet}">
<DockPanel Margin="{StaticResource SettingItemMargin}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock
Margin="8,0,0,0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkSingGeoRuleSetDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbSingGeoRuleSetDoc}" />
</Hyperlink>
</TextBlock>
<Button
x:Name="btnImportDefSingGeoRuleSets"
Margin="8,0,0,0"
Content="{x:Static resx:ResUI.TbSettingSingGeoImportDefRuleSets}"
Cursor="Hand"
Style="{StaticResource DefButton}" />
</StackPanel>
<Grid>
<TextBox
Name="txtSingGeoRuleSets"
Width="940"
DockPanel.Dock="Bottom"
VerticalAlignment="Stretch"
Margin="{StaticResource SettingItemMargin}"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbSettingsSingGeoRuleSets}"
AcceptsReturn="True"
BorderThickness="1"
Style="{StaticResource MaterialDesignOutlinedTextBox}"
TextWrapping="Wrap" HorizontalAlignment="Stretch"
VerticalScrollBarVisibility="Auto" />
</Grid>
</DockPanel>
</TabItem>
</TabControl>
<TabControl x:Name="tabBasic"> <TabControl x:Name="tabBasic">
<TabItem Header="{x:Static resx:ResUI.TbRoutingTabProxy}"> <TabItem Header="{x:Static resx:ResUI.TbRoutingTabProxy}">
@ -241,27 +276,27 @@
<ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<GroupBox <GroupBox
Grid.Column="0" Grid.Column="0"
Header="Domain" Header="Domain"
Style="{StaticResource MyGroupBox}"> Style="{StaticResource MyGroupBox}">
<TextBox <TextBox
Name="txtProxyDomain" Name="txtProxyDomain"
AcceptsReturn="True" AcceptsReturn="True"
Style="{StaticResource DefTextBox}" Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" /> VerticalScrollBarVisibility="Auto" />
</GroupBox> </GroupBox>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" /> <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
<GroupBox <GroupBox
Grid.Column="2" Grid.Column="2"
Header="IP" Header="IP"
Style="{StaticResource MyGroupBox}"> Style="{StaticResource MyGroupBox}">
<TextBox <TextBox
Name="txtProxyIP" Name="txtProxyIP"
AcceptsReturn="True" AcceptsReturn="True"
Style="{StaticResource DefTextBox}" Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" /> VerticalScrollBarVisibility="Auto" />
</GroupBox> </GroupBox>
</Grid> </Grid>
</TabItem> </TabItem>
@ -274,27 +309,27 @@
<ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<GroupBox <GroupBox
Grid.Column="0" Grid.Column="0"
Header="Domain" Header="Domain"
Style="{StaticResource MyGroupBox}"> Style="{StaticResource MyGroupBox}">
<TextBox <TextBox
Name="txtDirectDomain" Name="txtDirectDomain"
AcceptsReturn="True" AcceptsReturn="True"
Style="{StaticResource DefTextBox}" Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" /> VerticalScrollBarVisibility="Auto" />
</GroupBox> </GroupBox>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" /> <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
<GroupBox <GroupBox
Grid.Column="2" Grid.Column="2"
Header="IP" Header="IP"
Style="{StaticResource MyGroupBox}"> Style="{StaticResource MyGroupBox}">
<TextBox <TextBox
Name="txtDirectIP" Name="txtDirectIP"
AcceptsReturn="True" AcceptsReturn="True"
Style="{StaticResource DefTextBox}" Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" /> VerticalScrollBarVisibility="Auto" />
</GroupBox> </GroupBox>
</Grid> </Grid>
</TabItem> </TabItem>
@ -307,30 +342,65 @@
<ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<GroupBox <GroupBox
Grid.Column="0" Grid.Column="0"
Header="Domain" Header="Domain"
Style="{StaticResource MyGroupBox}"> Style="{StaticResource MyGroupBox}">
<TextBox <TextBox
Name="txtBlockDomain" Name="txtBlockDomain"
AcceptsReturn="True" AcceptsReturn="True"
Style="{StaticResource DefTextBox}" Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" /> VerticalScrollBarVisibility="Auto" />
</GroupBox> </GroupBox>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" /> <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
<GroupBox <GroupBox
Grid.Column="2" Grid.Column="2"
Header="IP" Header="IP"
Style="{StaticResource MyGroupBox}"> Style="{StaticResource MyGroupBox}">
<TextBox <TextBox
Name="txtBlockIP" Name="txtBlockIP"
AcceptsReturn="True" AcceptsReturn="True"
Style="{StaticResource DefTextBox}" Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" /> VerticalScrollBarVisibility="Auto" />
</GroupBox> </GroupBox>
</Grid> </Grid>
</TabItem> </TabItem>
<TabItem Header="{x:Static resx:ResUI.TbRoutingTabRuleSet}">
<DockPanel Margin="{StaticResource SettingItemMargin}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock
Margin="8,0,0,0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkSingGeoRuleSetDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbSingGeoRuleSetDoc}" />
</Hyperlink>
</TextBlock>
<Button
x:Name="btnImportDefSingGeoRuleSets2"
Margin="8,0,0,0"
Content="{x:Static resx:ResUI.TbSettingSingGeoImportDefRuleSets}"
Cursor="Hand"
Style="{StaticResource DefButton}" />
</StackPanel>
<Grid>
<TextBox
Name="txtSingGeoRuleSets2"
Width="940"
DockPanel.Dock="Bottom"
VerticalAlignment="Stretch"
Margin="{StaticResource SettingItemMargin}"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbSettingsSingGeoRuleSets}"
AcceptsReturn="True"
BorderThickness="1"
Style="{StaticResource MaterialDesignOutlinedTextBox}"
TextWrapping="Wrap" HorizontalAlignment="Stretch"
VerticalScrollBarVisibility="Auto" />
</Grid>
</DockPanel>
</TabItem>
</TabControl> </TabControl>
</DockPanel> </DockPanel>
</DockPanel> </DockPanel>

View file

@ -60,6 +60,8 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.DirectIP, v => v.txtDirectIP.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.DirectIP, v => v.txtDirectIP.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.BlockDomain, v => v.txtBlockDomain.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.BlockDomain, v => v.txtBlockDomain.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.BlockIP, v => v.txtBlockIP.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.BlockIP, v => v.txtBlockIP.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SingGeoRuleSets, v => v.txtSingGeoRuleSets.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SingGeoRuleSets, v => v.txtSingGeoRuleSets2.Text).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.enableRoutingBasic, v => v.menuRoutingBasic.Visibility).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.enableRoutingBasic, v => v.menuRoutingBasic.Visibility).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.enableRoutingAdvanced, v => v.menuRoutingAdvanced.Visibility).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.enableRoutingAdvanced, v => v.menuRoutingAdvanced.Visibility).DisposeWith(disposables);
@ -73,6 +75,8 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.RoutingAdvancedSetDefaultCmd, v => v.menuRoutingAdvancedSetDefault).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RoutingAdvancedSetDefaultCmd, v => v.menuRoutingAdvancedSetDefault).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RoutingAdvancedImportRulesCmd, v => v.menuRoutingAdvancedImportRules).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RoutingAdvancedImportRulesCmd, v => v.menuRoutingAdvancedImportRules).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RoutingAdvancedImportRulesCmd, v => v.menuRoutingAdvancedImportRules2).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RoutingAdvancedImportRulesCmd, v => v.menuRoutingAdvancedImportRules2).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RoutingImportSingGeoDefRuleSetsCmd, v => v.btnImportDefSingGeoRuleSets).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RoutingImportSingGeoDefRuleSetsCmd, v => v.btnImportDefSingGeoRuleSets2).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
}); });
@ -146,5 +150,10 @@ namespace v2rayN.Views
this.Close(); this.Close();
} }
} }
private void linkSingGeoRuleSetDoc_Click(object sender, RoutedEventArgs e)
{
Utils.ProcessStart("https://sing-box.sagernet.org/configuration/rule-set/");
}
} }
} }

View file

@ -30,6 +30,9 @@
<ItemGroup> <ItemGroup>
<AdditionalFiles Include="app.manifest" /> <AdditionalFiles Include="app.manifest" />
<EmbeddedResource Include="Sample\singbox_geo_rulesets">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="Sample\SingboxSampleOutbound" /> <EmbeddedResource Include="Sample\SingboxSampleOutbound" />
<EmbeddedResource Include="Sample\SingboxSampleClientConfig"> <EmbeddedResource Include="Sample\SingboxSampleClientConfig">
<CopyToOutputDirectory>Never</CopyToOutputDirectory> <CopyToOutputDirectory>Never</CopyToOutputDirectory>