Compare commits

...

6 commits

Author SHA1 Message Date
2dust
a372d8902e up 7.3.0
Some checks are pending
release macos / build (Release) (push) Waiting to run
release / build (Release) (push) Waiting to run
2024-12-05 20:08:23 +08:00
2dust
c38c62e4c3 Add automatic batching during speed test and real ping 2024-12-05 19:48:42 +08:00
2dust
8aceff7480 Enhanced testing function
Separate xray-core and sing-box-core testing
2024-12-05 15:21:16 +08:00
2dust
736c450161 Improve the code 2024-12-05 14:05:12 +08:00
2dust
3b63a3d308 Fix
https://github.com/2dust/v2rayN/issues/6216
2024-12-05 14:04:39 +08:00
2dust
4f56174c8f Bug fix
https://github.com/2dust/v2rayN/issues/6219
2024-12-05 12:16:53 +08:00
17 changed files with 183 additions and 101 deletions

View file

@ -1029,12 +1029,11 @@ namespace ServiceLib.Handler
public static async Task<ProfileItem?> GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType) public static async Task<ProfileItem?> GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
{ {
ProfileItem? itemSocks = null; ProfileItem? itemSocks = null;
var preCoreType = ECoreType.sing_box;
if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun) if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun)
{ {
itemSocks = new ProfileItem() itemSocks = new ProfileItem()
{ {
CoreType = preCoreType, CoreType = ECoreType.sing_box,
ConfigType = EConfigType.SOCKS, ConfigType = EConfigType.SOCKS,
Address = Global.Loopback, Address = Global.Loopback,
Sni = node.Address, //Tun2SocksAddress Sni = node.Address, //Tun2SocksAddress
@ -1043,7 +1042,7 @@ namespace ServiceLib.Handler
} }
else if ((node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0)) else if ((node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0))
{ {
preCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray; var preCoreType = config.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
itemSocks = new ProfileItem() itemSocks = new ProfileItem()
{ {
CoreType = preCoreType, CoreType = preCoreType,

View file

@ -174,7 +174,7 @@ namespace ServiceLib.Handler
var itemSocks = await ConfigHandler.GetPreSocksItem(_config, node, coreType); var itemSocks = await ConfigHandler.GetPreSocksItem(_config, node, coreType);
if (itemSocks != null) if (itemSocks != null)
{ {
var preCoreType = _config.RunningCoreType = itemSocks.CoreType ?? ECoreType.sing_box; var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
var fileName = Utils.GetConfigPath(Global.CorePreConfigFileName); var fileName = Utils.GetConfigPath(Global.CorePreConfigFileName);
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName); var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName);
if (result.Success) if (result.Success)

View file

@ -171,6 +171,7 @@
public int SpeedTestTimeout { get; set; } public int SpeedTestTimeout { get; set; }
public string SpeedTestUrl { get; set; } public string SpeedTestUrl { get; set; }
public string SpeedPingTestUrl { get; set; } public string SpeedPingTestUrl { get; set; }
public int SpeedTestPageSize { get; set; }
} }
[Serializable] [Serializable]

View file

@ -349,20 +349,20 @@ namespace ServiceLib.Models
public string? path { get; set; } public string? path { get; set; }
public string? host { get; set; } public string? host { get; set; }
public string? mode { get; set; } public string? mode { get; set; }
public string? scMaxEachPostBytes { get; set; } public object? scMaxEachPostBytes { get; set; }
public string? scMaxConcurrentPosts { get; set; } public object? scMaxConcurrentPosts { get; set; }
public string? scMinPostsIntervalMs { get; set; } public object? scMinPostsIntervalMs { get; set; }
public Xmux4Ray? xmux { get; set; } //public Xmux4Ray? xmux { get; set; }
public object? extra { get; set; } public object? extra { get; set; }
} }
public class Xmux4Ray //public class Xmux4Ray
{ //{
public int? maxConcurrency { get; set; } // public object? maxConcurrency { get; set; }
public int? maxConnections { get; set; } // public object? maxConnections { get; set; }
public int? cMaxReuseTimes { get; set; } // public object? cMaxReuseTimes { get; set; }
public int? cMaxLifetimeMs { get; set; } // public object? cMaxLifetimeMs { get; set; }
} //}
public class HttpSettings4Ray public class HttpSettings4Ray
{ {

View file

@ -3337,6 +3337,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Number per time for auto batch during speedtest(max 1000) 的本地化字符串。
/// </summary>
public static string TbSettingsSpeedTestPageSize {
get {
return ResourceManager.GetString("TbSettingsSpeedTestPageSize", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。 /// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。
/// </summary> /// </summary>

View file

@ -1384,4 +1384,7 @@
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>Hide to tray when closing the window</value> <value>Hide to tray when closing the window</value>
</data> </data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value>
</data>
</root> </root>

View file

@ -1384,4 +1384,7 @@
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>Hide to tray when closing the window</value> <value>Hide to tray when closing the window</value>
</data> </data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value>
</data>
</root> </root>

View file

@ -1384,4 +1384,7 @@
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>Hide to tray when closing the window</value> <value>Hide to tray when closing the window</value>
</data> </data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value>
</data>
</root> </root>

View file

@ -1381,4 +1381,7 @@
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>关闭窗口时隐藏至托盘</value> <value>关闭窗口时隐藏至托盘</value>
</data> </data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>测速时自动分批的每批数量最大1000</value>
</data>
</root> </root>

View file

@ -1381,4 +1381,7 @@
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>關閉視窗時隱藏至托盤</value> <value>關閉視窗時隱藏至托盤</value>
</data> </data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>測速時自動分批的每批數量最大1000</value>
</data>
</root> </root>

View file

@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Version>7.2.2</Version> <Version>7.3.0</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View file

@ -8,19 +8,16 @@ namespace ServiceLib.Services
public class SpeedtestService public class SpeedtestService
{ {
private Config? _config; private Config? _config;
private List<ServerTestItem> _selecteds;
private ESpeedActionType _actionType;
private Action<SpeedTestResult>? _updateFunc; private Action<SpeedTestResult>? _updateFunc;
private bool _exitLoop = false; private bool _exitLoop = false;
public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc) public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc)
{ {
_config = config; _config = config;
_actionType = actionType;
_updateFunc = updateFunc; _updateFunc = updateFunc;
_selecteds = 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 == EConfigType.Custom)
@ -31,7 +28,7 @@ namespace ServiceLib.Services
{ {
continue; continue;
} }
_selecteds.Add(new ServerTestItem() lstSelected.Add(new ServerTestItem()
{ {
IndexId = it.IndexId, IndexId = it.IndexId,
Address = it.Address, Address = it.Address,
@ -39,8 +36,9 @@ namespace ServiceLib.Services
ConfigType = it.ConfigType ConfigType = it.ConfigType
}); });
} }
//clear test result //clear test result
foreach (var it in _selecteds) foreach (var it in lstSelected)
{ {
switch (actionType) switch (actionType)
{ {
@ -63,25 +61,59 @@ namespace ServiceLib.Services
} }
} }
switch (actionType)
{
case ESpeedActionType.Tcping:
Task.Run(RunTcping);
break;
case ESpeedActionType.Realping:
Task.Run(RunRealPing);
break;
case ESpeedActionType.Speedtest:
Task.Run(RunSpeedTestAsync);
break;
case ESpeedActionType.Mixedtest:
Task.Run(RunMixedtestAsync);
break;
}
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop); MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
Task.Run(async () => { await RunAsync(actionType, lstSelected); });
}
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected)
{
if (actionType == ESpeedActionType.Tcping)
{
await RunTcpingAsync(lstSelected);
return;
}
var pageSize = _config.SpeedTestItem.SpeedTestPageSize;
if (pageSize is <= 0 or > 1000)
{
pageSize = 1000;
}
List<List<ServerTestItem>> lstTest = new();
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard)).ToList();
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard).ToList();
for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)
{
lstTest.Add(lst1.Skip(num * pageSize).Take(pageSize).ToList());
}
for (var num = 0; num < (int)Math.Ceiling(lst2.Count * 1.0 / pageSize); num++)
{
lstTest.Add(lst2.Skip(num * pageSize).Take(pageSize).ToList());
}
foreach (var lst in lstTest)
{
switch (actionType)
{
case ESpeedActionType.Realping:
await RunRealPingAsync(lst);
break;
case ESpeedActionType.Speedtest:
await RunSpeedTestAsync(lst);
break;
case ESpeedActionType.Mixedtest:
await RunMixedTestAsync(lst);
break;
}
await Task.Delay(100);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
} }
private void ExitLoop(string x) private void ExitLoop(string x)
@ -91,12 +123,12 @@ namespace ServiceLib.Services
UpdateFunc("", ResUI.SpeedtestingStop); UpdateFunc("", ResUI.SpeedtestingStop);
} }
private async Task RunTcping() private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
{ {
try try
{ {
List<Task> tasks = []; List<Task> tasks = [];
foreach (var it in _selecteds) foreach (var it in selecteds)
{ {
if (it.ConfigType == EConfigType.Custom) if (it.ConfigType == EConfigType.Custom)
{ {
@ -106,7 +138,7 @@ namespace ServiceLib.Services
{ {
try try
{ {
int time = await GetTcpingTime(it.Address, it.Port); var time = await GetTcpingTime(it.Address, it.Port);
var output = FormatOut(time, Global.DelayUnit); var output = FormatOut(time, Global.DelayUnit);
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output); ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
@ -130,24 +162,22 @@ namespace ServiceLib.Services
} }
} }
private async Task RunRealPing() private async Task RunRealPingAsync(List<ServerTestItem> selecteds)
{ {
int pid = -1; var pid = -1;
try try
{ {
string msg = string.Empty; pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
if (pid < 0) if (pid < 0)
{ {
UpdateFunc("", ResUI.FailedToRunCore); UpdateFunc("", ResUI.FailedToRunCore);
return; return;
} }
DownloadService downloadHandle = new DownloadService(); var downloadHandle = new DownloadService();
List<Task> tasks = new(); List<Task> tasks = new();
foreach (var it in _selecteds) foreach (var it in selecteds)
{ {
if (!it.AllowTest) if (!it.AllowTest)
{ {
@ -162,11 +192,11 @@ namespace ServiceLib.Services
try try
{ {
WebProxy webProxy = new(Global.Loopback, it.Port); WebProxy webProxy = new(Global.Loopback, it.Port);
string output = await GetRealPingTime(downloadHandle, webProxy); var output = await GetRealPingTime(downloadHandle, webProxy);
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output); ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
UpdateFunc(it.IndexId, output); UpdateFunc(it.IndexId, output);
int.TryParse(output, out int delay); int.TryParse(output, out var delay);
it.Delay = delay; it.Delay = delay;
} }
catch (Exception ex) catch (Exception ex)
@ -191,27 +221,22 @@ namespace ServiceLib.Services
} }
} }
private async Task RunSpeedTestAsync() private async Task RunSpeedTestAsync(List<ServerTestItem> selecteds)
{ {
int pid = -1; var pid = -1;
//if (_actionType == ESpeedActionType.Mixedtest) pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
//{
// _selecteds = _selecteds.OrderBy(t => t.delay).ToList();
//}
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
if (pid < 0) if (pid < 0)
{ {
UpdateFunc("", ResUI.FailedToRunCore); UpdateFunc("", ResUI.FailedToRunCore);
return; return;
} }
string url = _config.SpeedTestItem.SpeedTestUrl; var url = _config.SpeedTestItem.SpeedTestUrl;
var timeout = _config.SpeedTestItem.SpeedTestTimeout; var timeout = _config.SpeedTestItem.SpeedTestTimeout;
DownloadService downloadHandle = new(); DownloadService downloadHandle = new();
foreach (var it in _selecteds) foreach (var it in selecteds)
{ {
if (_exitLoop) if (_exitLoop)
{ {
@ -241,7 +266,7 @@ namespace ServiceLib.Services
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) => await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
{ {
decimal.TryParse(msg, out decimal dec); decimal.TryParse(msg, out var dec);
if (dec > 0) if (dec > 0)
{ {
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg); ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
@ -254,26 +279,25 @@ namespace ServiceLib.Services
{ {
await CoreHandler.Instance.CoreStopPid(pid); await CoreHandler.Instance.CoreStopPid(pid);
} }
UpdateFunc("", ResUI.SpeedtestingCompleted);
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
} }
private async Task RunSpeedTestMulti() private async Task RunSpeedTestMulti(List<ServerTestItem> selecteds)
{ {
int pid = -1; var pid = -1;
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds); pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
if (pid < 0) if (pid < 0)
{ {
UpdateFunc("", ResUI.FailedToRunCore); UpdateFunc("", ResUI.FailedToRunCore);
return; return;
} }
string url = _config.SpeedTestItem.SpeedTestUrl; var url = _config.SpeedTestItem.SpeedTestUrl;
var timeout = _config.SpeedTestItem.SpeedTestTimeout; var timeout = _config.SpeedTestItem.SpeedTestTimeout;
DownloadService downloadHandle = new(); DownloadService downloadHandle = new();
foreach (var it in _selecteds) foreach (var it in selecteds)
{ {
if (_exitLoop) if (_exitLoop)
{ {
@ -303,7 +327,7 @@ namespace ServiceLib.Services
WebProxy webProxy = new(Global.Loopback, it.Port); WebProxy webProxy = new(Global.Loopback, it.Port);
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) => _ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
{ {
decimal.TryParse(msg, out decimal dec); decimal.TryParse(msg, out var dec);
if (dec > 0) if (dec > 0)
{ {
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg); ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
@ -319,35 +343,34 @@ namespace ServiceLib.Services
{ {
await CoreHandler.Instance.CoreStopPid(pid); await CoreHandler.Instance.CoreStopPid(pid);
} }
UpdateFunc("", ResUI.SpeedtestingCompleted);
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
} }
private async Task RunMixedtestAsync() private async Task RunMixedTestAsync(List<ServerTestItem> selecteds)
{ {
await RunRealPing(); await RunRealPingAsync(selecteds);
await Task.Delay(1000); await Task.Delay(1000);
await RunSpeedTestMulti(); await RunSpeedTestMulti(selecteds);
} }
private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy) private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy)
{ {
int responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10); var responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
//string output = Utile.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status; //string output = Utile.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
return FormatOut(responseTime, Global.DelayUnit); return FormatOut(responseTime, Global.DelayUnit);
} }
private async Task<int> GetTcpingTime(string url, int port) private async Task<int> GetTcpingTime(string url, int port)
{ {
int responseTime = -1; var responseTime = -1;
try try
{ {
if (!IPAddress.TryParse(url, out IPAddress? ipAddress)) if (!IPAddress.TryParse(url, out var ipAddress))
{ {
IPHostEntry ipHostInfo = Dns.GetHostEntry(url); var ipHostInfo = await Dns.GetHostEntryAsync(url);
ipAddress = ipHostInfo.AddressList.First(); ipAddress = ipHostInfo.AddressList.First();
} }

View file

@ -62,6 +62,7 @@ namespace ServiceLib.ViewModels
[Reactive] public int SpeedTestTimeout { get; set; } [Reactive] public int SpeedTestTimeout { get; set; }
[Reactive] public string SpeedTestUrl { get; set; } [Reactive] public string SpeedTestUrl { get; set; }
[Reactive] public string SpeedPingTestUrl { get; set; } [Reactive] public string SpeedPingTestUrl { get; set; }
[Reactive] public int SpeedTestPageSize { get; set; }
[Reactive] public bool EnableHWA { get; set; } [Reactive] public bool EnableHWA { get; set; }
[Reactive] public string SubConvertUrl { get; set; } [Reactive] public string SubConvertUrl { get; set; }
[Reactive] public int MainGirdOrientation { get; set; } [Reactive] public int MainGirdOrientation { get; set; }
@ -175,6 +176,7 @@ namespace ServiceLib.ViewModels
CurrentFontFamily = _config.UiItem.CurrentFontFamily; CurrentFontFamily = _config.UiItem.CurrentFontFamily;
SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout; SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout;
SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl; SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl;
SpeedTestPageSize = _config.SpeedTestItem.SpeedTestPageSize;
SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl; SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl;
EnableHWA = _config.GuiItem.EnableHWA; EnableHWA = _config.GuiItem.EnableHWA;
SubConvertUrl = _config.ConstItem.SubConvertUrl; SubConvertUrl = _config.ConstItem.SubConvertUrl;
@ -325,6 +327,7 @@ namespace ServiceLib.ViewModels
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit; _config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
_config.UiItem.CurrentFontFamily = CurrentFontFamily; _config.UiItem.CurrentFontFamily = CurrentFontFamily;
_config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout; _config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout;
_config.SpeedTestItem.SpeedTestPageSize = SpeedTestPageSize;
_config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl; _config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl;
_config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl; _config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl;
_config.GuiItem.EnableHWA = EnableHWA; _config.GuiItem.EnableHWA = EnableHWA;

View file

@ -532,26 +532,40 @@
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="16" Grid.Row="15"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamily}" /> Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamily}" />
<ComboBox <ComboBox
x:Name="cmbcurrentFontFamily" x:Name="cmbcurrentFontFamily"
Grid.Row="16" Grid.Row="15"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Classes="Margin8" Classes="Margin8"
MaxDropDownHeight="1000" /> MaxDropDownHeight="1000" />
<TextBlock <TextBlock
Grid.Row="16" Grid.Row="15"
Grid.Column="2" Grid.Column="2"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyLinuxTip}" Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyLinuxTip}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<TextBlock
Grid.Row="16"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsSpeedTestPageSize}" />
<TextBox
x:Name="txtSpeedTestPageSize"
Grid.Row="16"
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="17" Grid.Row="17"
Grid.Column="0" Grid.Column="0"

View file

@ -138,6 +138,7 @@ namespace v2rayN.Desktop.Views
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestPageSize, v => v.txtSpeedTestPageSize.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);

View file

@ -698,7 +698,7 @@
HorizontalAlignment="Left" /> HorizontalAlignment="Left" />
<TextBlock <TextBlock
Grid.Row="14" Grid.Row="13"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin8}" Margin="{StaticResource Margin8}"
VerticalAlignment="Center" VerticalAlignment="Center"
@ -706,6 +706,22 @@
Text="{x:Static resx:ResUI.TbSettingsAutoUpdateInterval}" /> Text="{x:Static resx:ResUI.TbSettingsAutoUpdateInterval}" />
<TextBox <TextBox
x:Name="txtautoUpdateInterval" x:Name="txtautoUpdateInterval"
Grid.Row="13"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="14"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsTrayMenuServersLimit}" />
<TextBox
x:Name="txttrayMenuServersLimit"
Grid.Row="14" Grid.Row="14"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
@ -719,15 +735,23 @@
Margin="{StaticResource Margin8}" Margin="{StaticResource Margin8}"
VerticalAlignment="Center" VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}" Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsTrayMenuServersLimit}" /> Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamily}" />
<TextBox <ComboBox
x:Name="txttrayMenuServersLimit" x:Name="cmbcurrentFontFamily"
Grid.Row="15" Grid.Row="15"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Margin="{StaticResource Margin8}" Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" MaxDropDownHeight="1000"
Style="{StaticResource DefTextBox}" /> Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="15"
Grid.Column="2"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}"
TextWrapping="Wrap" />
<TextBlock <TextBlock
Grid.Row="16" Grid.Row="16"
@ -735,23 +759,15 @@
Margin="{StaticResource Margin8}" Margin="{StaticResource Margin8}"
VerticalAlignment="Center" VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}" Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamily}" /> Text="{x:Static resx:ResUI.TbSettingsSpeedTestPageSize}" />
<ComboBox <TextBox
x:Name="cmbcurrentFontFamily" x:Name="txtSpeedTestPageSize"
Grid.Row="16" Grid.Row="16"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Margin="{StaticResource Margin8}" Margin="{StaticResource Margin8}"
MaxDropDownHeight="1000" HorizontalAlignment="Left"
Style="{StaticResource DefComboBox}" /> Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="16"
Grid.Column="2"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}"
TextWrapping="Wrap" />
<TextBlock <TextBlock
Grid.Row="17" Grid.Row="17"

View file

@ -149,6 +149,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestPageSize, v => v.txtSpeedTestPageSize.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableHWA, v => v.togEnableHWA.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.EnableHWA, v => v.togEnableHWA.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);