mirror of https://github.com/2dust/v2rayN
External routing rules templates + regional presets support (#5840)
* External routing rules templates + auto download geo file if repo changed * Regional presets supportpull/5853/head
parent
a5122b656d
commit
2edbbc523a
|
@ -0,0 +1,8 @@
|
||||||
|
namespace ServiceLib.Enums
|
||||||
|
{
|
||||||
|
public enum EPresetType
|
||||||
|
{
|
||||||
|
Default = 0,
|
||||||
|
Russia = 1,
|
||||||
|
}
|
||||||
|
}
|
|
@ -126,6 +126,11 @@
|
||||||
@"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/refs/heads/release/sing-box/rule-set-{0}/{1}.srs",
|
@"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/refs/heads/release/sing-box/rule-set-{0}/{1}.srs",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static readonly List<string> RoutingRulesSources = new() {
|
||||||
|
"", //Default
|
||||||
|
@"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-custom-routing-list/refs/heads/main/template.json",
|
||||||
|
};
|
||||||
|
|
||||||
public static readonly Dictionary<string, string> UserAgentTexts = new()
|
public static readonly Dictionary<string, string> UserAgentTexts = new()
|
||||||
{
|
{
|
||||||
{"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" },
|
{"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" },
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using System.Data;
|
using ServiceLib.Common;
|
||||||
|
using System.Data;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace ServiceLib.Handler
|
namespace ServiceLib.Handler
|
||||||
|
@ -1616,6 +1618,79 @@ namespace ServiceLib.Handler
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int InitRouting(Config config, bool blImportAdvancedRules = false)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(config.constItem.routeRulesTemplateSourceUrl))
|
||||||
|
{
|
||||||
|
InitExternalRouting(config, blImportAdvancedRules);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InitBuiltinRouting(config, blImportAdvancedRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetLockedRoutingItem(config) == null)
|
||||||
|
{
|
||||||
|
var item1 = new RoutingItem()
|
||||||
|
{
|
||||||
|
remarks = "locked",
|
||||||
|
url = string.Empty,
|
||||||
|
locked = true,
|
||||||
|
};
|
||||||
|
AddBatchRoutingRules(ref item1, Utils.GetEmbedText(Global.CustomRoutingFileName + "locked"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int InitExternalRouting(Config config, bool blImportAdvancedRules = false)
|
||||||
|
{
|
||||||
|
DownloadService downloadHandle = new DownloadService();
|
||||||
|
var templateContent = Task.Run(() => downloadHandle.TryDownloadString(config.constItem.routeRulesTemplateSourceUrl, false, "")).Result;
|
||||||
|
if (String.IsNullOrEmpty(templateContent))
|
||||||
|
return InitBuiltinRouting(config, blImportAdvancedRules); // fallback
|
||||||
|
|
||||||
|
var template = JsonUtils.Deserialize<RoutingTemplate>(templateContent);
|
||||||
|
if (template == null)
|
||||||
|
return InitBuiltinRouting(config, blImportAdvancedRules); // fallback
|
||||||
|
|
||||||
|
var items = AppHandler.Instance.RoutingItems();
|
||||||
|
var maxSort = items.Count;
|
||||||
|
|
||||||
|
if (blImportAdvancedRules || items.Where(t => t.remarks.StartsWith(template.version)).ToList().Count <= 0)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < template.routingItems.Length; i++)
|
||||||
|
{
|
||||||
|
var item = template.routingItems[i];
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(item.url) && String.IsNullOrEmpty(item.ruleSet))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var ruleSetsString = !String.IsNullOrEmpty(item.ruleSet)
|
||||||
|
? item.ruleSet
|
||||||
|
: Task.Run(() => downloadHandle.TryDownloadString(item.url, false, "")).Result;
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(ruleSetsString))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
item.remarks = $"{template.version}-{item.remarks}";
|
||||||
|
item.enabled = true;
|
||||||
|
item.sort = ++maxSort;
|
||||||
|
item.url = string.Empty;
|
||||||
|
|
||||||
|
AddBatchRoutingRules(ref item, ruleSetsString);
|
||||||
|
|
||||||
|
//first rule as default at first startup
|
||||||
|
if (!blImportAdvancedRules && i == 0)
|
||||||
|
{
|
||||||
|
SetDefaultRouting(config, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static int InitBuiltinRouting(Config config, bool blImportAdvancedRules = false)
|
public static int InitBuiltinRouting(Config config, bool blImportAdvancedRules = false)
|
||||||
{
|
{
|
||||||
var ver = "V3-";
|
var ver = "V3-";
|
||||||
|
@ -1655,17 +1730,6 @@ namespace ServiceLib.Handler
|
||||||
SetDefaultRouting(config, item2);
|
SetDefaultRouting(config, item2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetLockedRoutingItem(config) == null)
|
|
||||||
{
|
|
||||||
var item1 = new RoutingItem()
|
|
||||||
{
|
|
||||||
remarks = "locked",
|
|
||||||
url = string.Empty,
|
|
||||||
locked = true,
|
|
||||||
};
|
|
||||||
AddBatchRoutingRules(ref item1, Utils.GetEmbedText(Global.CustomRoutingFileName + "locked"));
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1724,5 +1788,31 @@ namespace ServiceLib.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion DNS
|
#endregion DNS
|
||||||
|
|
||||||
|
#region Presets
|
||||||
|
|
||||||
|
public static bool ApplyPreset(Config config, EPresetType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case EPresetType.Default:
|
||||||
|
config.constItem.geoSourceUrl = "";
|
||||||
|
config.constItem.srsSourceUrl = "";
|
||||||
|
config.constItem.routeRulesTemplateSourceUrl = "";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case EPresetType.Russia:
|
||||||
|
config.constItem.geoSourceUrl = Global.GeoFilesSources[1];
|
||||||
|
config.constItem.srsSourceUrl = Global.SingboxRulesetSources[1];
|
||||||
|
config.constItem.routeRulesTemplateSourceUrl = Global.RoutingRulesSources[1];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -142,6 +142,7 @@
|
||||||
public string subConvertUrl { get; set; } = string.Empty;
|
public string subConvertUrl { get; set; } = string.Empty;
|
||||||
public string? geoSourceUrl { get; set; }
|
public string? geoSourceUrl { get; set; }
|
||||||
public string? srsSourceUrl { get; set; }
|
public string? srsSourceUrl { get; set; }
|
||||||
|
public string? routeRulesTemplateSourceUrl { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace ServiceLib.Models
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class RoutingTemplate
|
||||||
|
{
|
||||||
|
public string version { get; set; }
|
||||||
|
public RoutingItem[] routingItems { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1113,6 +1113,33 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Regional presets 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string menuPresets {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("menuPresets", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Default 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string menuPresetsDefault {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("menuPresetsDefault", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Russia 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string menuPresetsRussia {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("menuPresetsRussia", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Auto column width adjustment 的本地化字符串。
|
/// 查找类似 Auto column width adjustment 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -3013,6 +3040,17 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Routing rules source (optional) 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsRoutingRulesSource
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ResourceManager.GetString("TbSettingsRoutingRulesSource", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 HTTP Port 的本地化字符串。
|
/// 查找类似 HTTP Port 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1336,4 +1336,16 @@
|
||||||
<data name="UpgradeAppNotExistTip" xml:space="preserve">
|
<data name="UpgradeAppNotExistTip" xml:space="preserve">
|
||||||
<value>UpgradeApp does not exist</value>
|
<value>UpgradeApp does not exist</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsRoutingRulesSource" xml:space="preserve">
|
||||||
|
<value>Routing rules source (optional)</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuPresets" xml:space="preserve">
|
||||||
|
<value>Regional presets</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuPresetsDefault" xml:space="preserve">
|
||||||
|
<value>Default</value>
|
||||||
|
</data>
|
||||||
|
<data name="menuPresetsRussia" xml:space="preserve">
|
||||||
|
<value>Russia</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -44,6 +44,10 @@ namespace ServiceLib.ViewModels
|
||||||
public ReactiveCommand<Unit, Unit> ClearServerStatisticsCmd { get; }
|
public ReactiveCommand<Unit, Unit> ClearServerStatisticsCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> OpenTheFileLocationCmd { get; }
|
public ReactiveCommand<Unit, Unit> OpenTheFileLocationCmd { get; }
|
||||||
|
|
||||||
|
//Presets
|
||||||
|
public ReactiveCommand<Unit, Unit> PresetDefaultCmd { get; }
|
||||||
|
public ReactiveCommand<Unit, Unit> PresetRussiaCmd { get; }
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> ReloadCmd { get; }
|
public ReactiveCommand<Unit, Unit> ReloadCmd { get; }
|
||||||
|
|
||||||
[Reactive]
|
[Reactive]
|
||||||
|
@ -181,6 +185,16 @@ namespace ServiceLib.ViewModels
|
||||||
await Reload();
|
await Reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
PresetDefaultCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
|
{
|
||||||
|
await ApplyPreset(EPresetType.Default);
|
||||||
|
});
|
||||||
|
|
||||||
|
PresetRussiaCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
|
{
|
||||||
|
await ApplyPreset(EPresetType.Russia);
|
||||||
|
});
|
||||||
|
|
||||||
#endregion WhenAnyValue && ReactiveCommand
|
#endregion WhenAnyValue && ReactiveCommand
|
||||||
|
|
||||||
AutoHideStartup();
|
AutoHideStartup();
|
||||||
|
@ -188,7 +202,7 @@ namespace ServiceLib.ViewModels
|
||||||
|
|
||||||
private void Init()
|
private void Init()
|
||||||
{
|
{
|
||||||
ConfigHandler.InitBuiltinRouting(_config);
|
ConfigHandler.InitRouting(_config);
|
||||||
ConfigHandler.InitBuiltinDNS(_config);
|
ConfigHandler.InitBuiltinDNS(_config);
|
||||||
CoreHandler.Instance.Init(_config, UpdateHandler);
|
CoreHandler.Instance.Init(_config, UpdateHandler);
|
||||||
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);
|
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);
|
||||||
|
@ -431,7 +445,7 @@ namespace ServiceLib.ViewModels
|
||||||
var ret = await _updateView?.Invoke(EViewAction.RoutingSettingWindow, null);
|
var ret = await _updateView?.Invoke(EViewAction.RoutingSettingWindow, null);
|
||||||
if (ret == true)
|
if (ret == true)
|
||||||
{
|
{
|
||||||
ConfigHandler.InitBuiltinRouting(_config);
|
ConfigHandler.InitRouting(_config);
|
||||||
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
|
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
|
||||||
Reload();
|
Reload();
|
||||||
}
|
}
|
||||||
|
@ -543,5 +557,22 @@ namespace ServiceLib.ViewModels
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion core job
|
#endregion core job
|
||||||
|
|
||||||
|
#region Presets
|
||||||
|
|
||||||
|
public async Task ApplyPreset(EPresetType type)
|
||||||
|
{
|
||||||
|
ConfigHandler.ApplyPreset(_config, type);
|
||||||
|
|
||||||
|
await new UpdateService().UpdateGeoFileAll(_config, UpdateHandler);
|
||||||
|
|
||||||
|
ConfigHandler.InitRouting(_config);
|
||||||
|
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
|
||||||
|
|
||||||
|
ConfigHandler.SaveConfig(_config, false);
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -67,6 +67,7 @@ namespace ServiceLib.ViewModels
|
||||||
[Reactive] public int MainGirdOrientation { get; set; }
|
[Reactive] public int MainGirdOrientation { get; set; }
|
||||||
[Reactive] public string GeoFileSourceUrl { get; set; }
|
[Reactive] public string GeoFileSourceUrl { get; set; }
|
||||||
[Reactive] public string SrsFileSourceUrl { get; set; }
|
[Reactive] public string SrsFileSourceUrl { get; set; }
|
||||||
|
[Reactive] public string RoutingRulesSourceUrl { get; set; }
|
||||||
|
|
||||||
#endregion UI
|
#endregion UI
|
||||||
|
|
||||||
|
@ -168,6 +169,7 @@ namespace ServiceLib.ViewModels
|
||||||
MainGirdOrientation = (int)_config.uiItem.mainGirdOrientation;
|
MainGirdOrientation = (int)_config.uiItem.mainGirdOrientation;
|
||||||
GeoFileSourceUrl = _config.constItem.geoSourceUrl;
|
GeoFileSourceUrl = _config.constItem.geoSourceUrl;
|
||||||
SrsFileSourceUrl = _config.constItem.srsSourceUrl;
|
SrsFileSourceUrl = _config.constItem.srsSourceUrl;
|
||||||
|
RoutingRulesSourceUrl = _config.constItem.routeRulesTemplateSourceUrl;
|
||||||
|
|
||||||
#endregion UI
|
#endregion UI
|
||||||
|
|
||||||
|
@ -322,6 +324,7 @@ namespace ServiceLib.ViewModels
|
||||||
_config.uiItem.mainGirdOrientation = (EGirdOrientation)MainGirdOrientation;
|
_config.uiItem.mainGirdOrientation = (EGirdOrientation)MainGirdOrientation;
|
||||||
_config.constItem.geoSourceUrl = GeoFileSourceUrl;
|
_config.constItem.geoSourceUrl = GeoFileSourceUrl;
|
||||||
_config.constItem.srsSourceUrl = SrsFileSourceUrl;
|
_config.constItem.srsSourceUrl = SrsFileSourceUrl;
|
||||||
|
_config.constItem.routeRulesTemplateSourceUrl = RoutingRulesSourceUrl;
|
||||||
|
|
||||||
//systemProxy
|
//systemProxy
|
||||||
_config.systemProxyItem.systemProxyExceptions = systemProxyExceptions;
|
_config.systemProxyItem.systemProxyExceptions = systemProxyExceptions;
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace ServiceLib.ViewModels
|
||||||
_updateView = updateView;
|
_updateView = updateView;
|
||||||
SelectedSource = new();
|
SelectedSource = new();
|
||||||
|
|
||||||
ConfigHandler.InitBuiltinRouting(_config);
|
ConfigHandler.InitRouting(_config);
|
||||||
|
|
||||||
enableRoutingAdvanced = _config.routingBasicItem.enableRoutingAdvanced;
|
enableRoutingAdvanced = _config.routingBasicItem.enableRoutingAdvanced;
|
||||||
domainStrategy = _config.routingBasicItem.domainStrategy;
|
domainStrategy = _config.routingBasicItem.domainStrategy;
|
||||||
|
@ -286,7 +286,7 @@ namespace ServiceLib.ViewModels
|
||||||
|
|
||||||
private async Task RoutingAdvancedImportRules()
|
private async Task RoutingAdvancedImportRules()
|
||||||
{
|
{
|
||||||
if (ConfigHandler.InitBuiltinRouting(_config, true) == 0)
|
if (ConfigHandler.InitRouting(_config, true) == 0)
|
||||||
{
|
{
|
||||||
RefreshRoutingItems();
|
RefreshRoutingItems();
|
||||||
IsModified = true;
|
IsModified = true;
|
||||||
|
|
|
@ -74,6 +74,10 @@
|
||||||
<MenuItem x:Name="menuRoutingSetting" Header="{x:Static resx:ResUI.menuRoutingSetting}" />
|
<MenuItem x:Name="menuRoutingSetting" Header="{x:Static resx:ResUI.menuRoutingSetting}" />
|
||||||
<MenuItem x:Name="menuDNSSetting" Header="{x:Static resx:ResUI.menuDNSSetting}" />
|
<MenuItem x:Name="menuDNSSetting" Header="{x:Static resx:ResUI.menuDNSSetting}" />
|
||||||
<MenuItem x:Name="menuGlobalHotkeySetting" Header="{x:Static resx:ResUI.menuGlobalHotkeySetting}" />
|
<MenuItem x:Name="menuGlobalHotkeySetting" Header="{x:Static resx:ResUI.menuGlobalHotkeySetting}" />
|
||||||
|
<MenuItem Header="{x:Static resx:ResUI.menuPresets}">
|
||||||
|
<MenuItem x:Name="menuPresetsDefault" Header="{x:Static resx:ResUI.menuPresetsDefault}" />
|
||||||
|
<MenuItem x:Name="menuPresetsRussia" Header="{x:Static resx:ResUI.menuPresetsRussia}" />
|
||||||
|
</MenuItem>
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem x:Name="menuRebootAsAdmin" Header="{x:Static resx:ResUI.menuRebootAsAdmin}" />
|
<MenuItem x:Name="menuRebootAsAdmin" Header="{x:Static resx:ResUI.menuRebootAsAdmin}" />
|
||||||
<MenuItem x:Name="menuSettingsSetUWP" Header="{x:Static resx:ResUI.TbSettingsSetUWP}" />
|
<MenuItem x:Name="menuSettingsSetUWP" Header="{x:Static resx:ResUI.TbSettingsSetUWP}" />
|
||||||
|
|
|
@ -76,6 +76,8 @@ namespace v2rayN.Desktop.Views
|
||||||
this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables);
|
||||||
|
this.BindCommand(ViewModel, vm => vm.PresetDefaultCmd, v => v.menuPresetsDefault).DisposeWith(disposables);
|
||||||
|
this.BindCommand(ViewModel, vm => vm.PresetRussiaCmd, v => v.menuPresetsRussia).DisposeWith(disposables);
|
||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
||||||
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
||||||
|
|
|
@ -366,6 +366,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" />
|
||||||
|
@ -638,6 +639,19 @@
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Width="300"
|
Width="300"
|
||||||
Classes="Margin8" />
|
Classes="Margin8" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="24"
|
||||||
|
Grid.Column="0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Classes="Margin8"
|
||||||
|
Text="{x:Static resx:ResUI.TbSettingsRoutingRulesSource}" />
|
||||||
|
<ComboBox
|
||||||
|
x:Name="cmbRoutingRulesSourceUrl"
|
||||||
|
Grid.Row="24"
|
||||||
|
Grid.Column="1"
|
||||||
|
Width="300"
|
||||||
|
Classes="Margin8" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
|
@ -91,6 +91,10 @@ namespace v2rayN.Desktop.Views
|
||||||
{
|
{
|
||||||
cmbSrsFilesSourceUrl.Items.Add(it);
|
cmbSrsFilesSourceUrl.Items.Add(it);
|
||||||
});
|
});
|
||||||
|
Global.RoutingRulesSources.ForEach(it =>
|
||||||
|
{
|
||||||
|
cmbRoutingRulesSourceUrl.Items.Add(it);
|
||||||
|
});
|
||||||
foreach (EGirdOrientation it in Enum.GetValues(typeof(EGirdOrientation)))
|
foreach (EGirdOrientation it in Enum.GetValues(typeof(EGirdOrientation)))
|
||||||
{
|
{
|
||||||
cmbMainGirdOrientation.Items.Add(it.ToString());
|
cmbMainGirdOrientation.Items.Add(it.ToString());
|
||||||
|
@ -142,6 +146,7 @@ namespace v2rayN.Desktop.Views
|
||||||
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.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.SelectedValue).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.SelectedValue).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.notProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.notProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.SelectedValue).DisposeWith(disposables);
|
||||||
|
|
|
@ -171,6 +171,16 @@
|
||||||
x:Name="menuGlobalHotkeySetting"
|
x:Name="menuGlobalHotkeySetting"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Header="{x:Static resx:ResUI.menuGlobalHotkeySetting}" />
|
Header="{x:Static resx:ResUI.menuGlobalHotkeySetting}" />
|
||||||
|
<MenuItem Height="{StaticResource MenuItemHeight}" Header="{x:Static resx:ResUI.menuPresets}">
|
||||||
|
<MenuItem
|
||||||
|
x:Name="menuPresetsDefault"
|
||||||
|
Height="{StaticResource MenuItemHeight}"
|
||||||
|
Header="{x:Static resx:ResUI.menuPresetsDefault}" />
|
||||||
|
<MenuItem
|
||||||
|
x:Name="menuPresetsRussia"
|
||||||
|
Height="{StaticResource MenuItemHeight}"
|
||||||
|
Header="{x:Static resx:ResUI.menuPresetsRussia}" />
|
||||||
|
</MenuItem>
|
||||||
<Separator Margin="-40,5" />
|
<Separator Margin="-40,5" />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuRebootAsAdmin"
|
x:Name="menuRebootAsAdmin"
|
||||||
|
|
|
@ -98,6 +98,8 @@ namespace v2rayN.Views
|
||||||
this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables);
|
||||||
|
this.BindCommand(ViewModel, vm => vm.PresetDefaultCmd, v => v.menuPresetsDefault).DisposeWith(disposables);
|
||||||
|
this.BindCommand(ViewModel, vm => vm.PresetRussiaCmd, v => v.menuPresetsRussia).DisposeWith(disposables);
|
||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
||||||
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
||||||
|
|
|
@ -530,6 +530,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" />
|
||||||
|
@ -879,6 +880,22 @@
|
||||||
Margin="{StaticResource Margin8}"
|
Margin="{StaticResource Margin8}"
|
||||||
IsEditable="True"
|
IsEditable="True"
|
||||||
Style="{StaticResource DefComboBox}" />
|
Style="{StaticResource DefComboBox}" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="24"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="{StaticResource Margin8}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
|
Text="{x:Static resx:ResUI.TbSettingsRoutingRulesSource}" />
|
||||||
|
<ComboBox
|
||||||
|
x:Name="cmbRoutingRulesSourceUrl"
|
||||||
|
Grid.Row="24"
|
||||||
|
Grid.Column="1"
|
||||||
|
Width="300"
|
||||||
|
Margin="{StaticResource Margin8}"
|
||||||
|
IsEditable="True"
|
||||||
|
Style="{StaticResource DefComboBox}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
|
@ -93,6 +93,10 @@ namespace v2rayN.Views
|
||||||
{
|
{
|
||||||
cmbSrsFilesSourceUrl.Items.Add(it);
|
cmbSrsFilesSourceUrl.Items.Add(it);
|
||||||
});
|
});
|
||||||
|
Global.RoutingRulesSources.ForEach(it =>
|
||||||
|
{
|
||||||
|
cmbRoutingRulesSourceUrl.Items.Add(it);
|
||||||
|
});
|
||||||
foreach (EGirdOrientation it in Enum.GetValues(typeof(EGirdOrientation)))
|
foreach (EGirdOrientation it in Enum.GetValues(typeof(EGirdOrientation)))
|
||||||
{
|
{
|
||||||
cmbMainGirdOrientation.Items.Add(it.ToString());
|
cmbMainGirdOrientation.Items.Add(it.ToString());
|
||||||
|
@ -155,6 +159,7 @@ namespace v2rayN.Views
|
||||||
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.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.Text).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.notProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).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);
|
||||||
|
|
Loading…
Reference in New Issue