Compare commits

...

6 Commits
7.8.0 ... 7.8.1

Author SHA1 Message Date
2dust
c3fdfcc4bd up 7.8.1 2025-02-08 16:49:59 +08:00
2dust
7ea8fae2da Improve test logic
Retest the failed part of the test and call it recursively.
Remove the number of batches that are automatically divided when testing parameters.
2025-02-08 16:43:40 +08:00
2dust
67ffa810d3 Optimize code and remove Action 2025-02-06 15:28:51 +08:00
2dust
ba2a636dd2 Fixed the system language judgment during the first run
https://github.com/2dust/v2rayN/issues/6638
2025-02-06 14:36:38 +08:00
2dust
d471336994 Adjust App Exit function
https://github.com/2dust/v2rayN/issues/6634
2025-02-05 17:31:13 +08:00
2dust
7e6482fdff Adjust hysteria core run arguments
https://github.com/2dust/v2rayN/issues/6635
2025-02-05 17:14:56 +08:00
22 changed files with 151 additions and 96 deletions

View File

@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<Version>7.8.0</Version>
<Version>7.8.1</Version>
</PropertyGroup>
<PropertyGroup>

View File

@@ -72,6 +72,7 @@ namespace ServiceLib
public const string LocalAppData = "V2RAYN_LOCAL_APPLICATION_DATA";
public const string V2RayLocalAsset = "V2RAY_LOCATION_ASSET";
public const string XrayLocalAsset = "XRAY_LOCATION_ASSET";
public const int SpeedTestPageSize = 1000;
public static readonly List<string> IEProxyProtocols =
[

View File

@@ -105,14 +105,9 @@ namespace ServiceLib.Handler
if (Utils.IsNullOrEmpty(config.UiItem.CurrentLanguage))
{
if (Thread.CurrentThread.CurrentCulture.Name.Equals("zh-cn", StringComparison.CurrentCultureIgnoreCase))
{
config.UiItem.CurrentLanguage = Global.Languages.First();
}
else
{
config.UiItem.CurrentLanguage = Global.Languages[2];
}
config.UiItem.CurrentLanguage = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.Equals("zh", StringComparison.CurrentCultureIgnoreCase)
? Global.Languages.First()
: Global.Languages[2];
}
config.ConstItem ??= new ConstItem();

View File

@@ -287,7 +287,7 @@ namespace ServiceLib.Handler
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
UpdateFunc(true, ex.Message);
UpdateFunc(mayNeedSudo, ex.Message);
return null;
}
}

View File

@@ -129,8 +129,8 @@ namespace ServiceLib.Handler
new CoreInfo
{
CoreType = ECoreType.hysteria,
CoreExes = ["hysteria-windows-amd64", "hysteria"],
Arguments = "-c {0}",
CoreExes = ["hysteria"],
Arguments = "",
Url = GetCoreUrl(ECoreType.hysteria),
},
@@ -180,7 +180,7 @@ namespace ServiceLib.Handler
{
CoreType = ECoreType.hysteria2,
CoreExes = ["hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria"],
Arguments = "-c {0}",
Arguments = "",
Url = GetCoreUrl(ECoreType.hysteria2),
},

View File

@@ -2094,6 +2094,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Starting retesting failed parts, {0} remaining. Press ESC to terminate... 的本地化字符串。
/// </summary>
public static string SpeedtestingTestFailedPart {
get {
return ResourceManager.GetString("SpeedtestingTestFailedPart", resourceCulture);
}
}
/// <summary>
/// 查找类似 Waiting for testing (press ESC to terminate)... 的本地化字符串。
/// </summary>

View File

@@ -1393,4 +1393,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>کپی کردن دستور پروکسی در کلیپ بورد</value>
</data>
</root>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
</data>
</root>

View File

@@ -1393,4 +1393,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value>
</data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
</data>
</root>

View File

@@ -1393,4 +1393,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value>
</data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
</data>
</root>

View File

@@ -1393,4 +1393,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value>
</data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
</data>
</root>

View File

@@ -1390,4 +1390,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>复制终端代理命令至剪贴板</value>
</data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>开始对失败部分进行重新测试,剩余 {0} 个。可按 ESC 终止...</value>
</data>
</root>

View File

@@ -1391,4 +1391,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>複製終端代理指令至剪貼簿</value>
</data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>開始對失敗部分進行重新測試,剩餘 {0} 個。可按 ESC 終止...</value>
</data>
</root>

View File

@@ -13,11 +13,69 @@ namespace ServiceLib.Services
private bool _exitLoop = false;
private static readonly string _tag = "SpeedtestService";
public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc)
public SpeedtestService(Config config, ESpeedActionType actionType, List<ProfileItem> selecteds, Action<SpeedTestResult> updateFunc)
{
_config = config;
_updateFunc = updateFunc;
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
Task.Run(async () =>
{
var lstSelected = GetClearItem(actionType, selecteds);
await RunAsync(actionType, lstSelected);
UpdateFunc("", ResUI.SpeedtestingCompleted);
});
}
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected, int pageSize = 0)
{
if (actionType == ESpeedActionType.Tcping)
{
await RunTcpingAsync(lstSelected);
return;
}
if (pageSize <= 0)
{
pageSize = lstSelected.Count < Global.SpeedTestPageSize ? lstSelected.Count : Global.SpeedTestPageSize;
}
var lstTest = GetTestBatchItem(lstSelected, pageSize);
List<ServerTestItem> lstFailed = new();
foreach (var lst in lstTest)
{
var ret = actionType switch
{
ESpeedActionType.Realping => await RunRealPingAsync(lst),
ESpeedActionType.Speedtest => await RunSpeedTestAsync(lst),
ESpeedActionType.Mixedtest => await RunMixedTestAsync(lst),
_ => true
};
if (ret == false)
{
lstFailed.AddRange(lst);
}
await Task.Delay(100);
}
//Retest the failed part
var pageSizeNext = pageSize / 2;
if (lstFailed.Count > 0 && pageSizeNext > 0)
{
if (_exitLoop)
{
UpdateFunc("", ResUI.SpeedtestingSkip);
return;
}
UpdateFunc("", string.Format(ResUI.SpeedtestingTestFailedPart, lstFailed.Count));
await RunAsync(actionType, lstFailed, pageSizeNext);
}
}
private List<ServerTestItem> GetClearItem(ESpeedActionType actionType, List<ProfileItem> selecteds)
{
var lstSelected = new List<ServerTestItem>();
foreach (var it in selecteds)
{
@@ -25,10 +83,12 @@ namespace ServiceLib.Services
{
continue;
}
if (it.Port <= 0)
{
continue;
}
lstSelected.Add(new ServerTestItem()
{
IndexId = it.IndexId,
@@ -62,25 +122,11 @@ namespace ServiceLib.Services
}
}
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
Task.Run(async () => { await RunAsync(actionType, lstSelected); });
return lstSelected;
}
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected)
private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
{
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();
@@ -94,27 +140,7 @@ namespace ServiceLib.Services
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);
return lstTest;
}
private void ExitLoop(string x)
@@ -164,7 +190,7 @@ namespace ServiceLib.Services
}
}
private async Task RunRealPingAsync(List<ServerTestItem> selecteds)
private async Task<bool> RunRealPingAsync(List<ServerTestItem> selecteds)
{
var pid = -1;
try
@@ -172,8 +198,7 @@ namespace ServiceLib.Services
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return;
return false;
}
var downloadHandle = new DownloadService();
@@ -221,16 +246,16 @@ namespace ServiceLib.Services
}
await ProfileExHandler.Instance.SaveTo();
}
return true;
}
private async Task RunSpeedTestAsync(List<ServerTestItem> selecteds)
private async Task<bool> RunSpeedTestAsync(List<ServerTestItem> selecteds)
{
var pid = -1;
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return;
return false;
}
var url = _config.SpeedTestItem.SpeedTestUrl;
@@ -283,16 +308,16 @@ namespace ServiceLib.Services
await ProcUtils.ProcessKill(pid);
}
await ProfileExHandler.Instance.SaveTo();
return true;
}
private async Task RunSpeedTestMulti(List<ServerTestItem> selecteds)
private async Task<bool> RunSpeedTestMulti(List<ServerTestItem> selecteds)
{
var pid = -1;
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return;
return false;
}
var url = _config.SpeedTestItem.SpeedTestUrl;
@@ -348,21 +373,30 @@ namespace ServiceLib.Services
await ProcUtils.ProcessKill(pid);
}
await ProfileExHandler.Instance.SaveTo();
return true;
}
private async Task RunMixedTestAsync(List<ServerTestItem> selecteds)
private async Task<bool> RunMixedTestAsync(List<ServerTestItem> selecteds)
{
await RunRealPingAsync(selecteds);
var ret = await RunRealPingAsync(selecteds);
if (ret == false)
{
return false;
}
await Task.Delay(1000);
await RunSpeedTestMulti(selecteds);
var ret2 = await RunSpeedTestMulti(selecteds);
if (ret2 == false)
{
return false;
}
return true;
}
private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy)
{
var responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
//string output = Utile.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
return FormatOut(responseTime, Global.DelayUnit);
}

View File

@@ -243,7 +243,7 @@ namespace ServiceLib.Services
_updateFunc?.Invoke(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, "geo"));
}
public async Task RunAvailabilityCheck(Action<bool, string> updateFunc)
public async Task<string> RunAvailabilityCheck()
{
var downloadHandle = new DownloadService();
var time = await downloadHandle.RunAvailabilityCheck(null);
@@ -255,7 +255,7 @@ namespace ServiceLib.Services
ip = $"({ipInfo?.country_code}) {ipInfo?.ip}";
}
updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time, ip));
return string.Format(ResUI.TestMeOutput, time, ip);
}
#region CheckUpdate private

View File

@@ -287,14 +287,15 @@ namespace ServiceLib.ViewModels
try
{
Logging.SaveLog("MyAppExitAsync Begin");
await SysProxyHandler.UpdateSysProxy(_config, true);
MessageBus.Current.SendMessage("", EMsgCommand.AppExit.ToString());
await ConfigHandler.SaveConfig(_config);
await SysProxyHandler.UpdateSysProxy(_config, true);
await ProfileExHandler.Instance.SaveTo();
await StatisticsHandler.Instance.SaveTo();
StatisticsHandler.Instance.Close();
await CoreHandler.Instance.CoreStop();
StatisticsHandler.Instance.Close();
Logging.SaveLog("MyAppExitAsync End");
}

View File

@@ -63,7 +63,7 @@ namespace ServiceLib.ViewModels
[Reactive] public int SpeedTestTimeout { get; set; }
[Reactive] public string SpeedTestUrl { get; set; }
[Reactive] public string SpeedPingTestUrl { get; set; }
[Reactive] public int SpeedTestPageSize { get; set; }
//[Reactive] public int SpeedTestPageSize { get; set; }
[Reactive] public bool EnableHWA { get; set; }
[Reactive] public string SubConvertUrl { get; set; }
[Reactive] public int MainGirdOrientation { get; set; }
@@ -178,7 +178,7 @@ namespace ServiceLib.ViewModels
CurrentFontFamily = _config.UiItem.CurrentFontFamily;
SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout;
SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl;
SpeedTestPageSize = _config.SpeedTestItem.SpeedTestPageSize;
//SpeedTestPageSize = _config.SpeedTestItem.SpeedTestPageSize;
SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl;
EnableHWA = _config.GuiItem.EnableHWA;
SubConvertUrl = _config.ConstItem.SubConvertUrl;
@@ -332,7 +332,7 @@ namespace ServiceLib.ViewModels
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
_config.UiItem.CurrentFontFamily = CurrentFontFamily;
_config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout;
_config.SpeedTestItem.SpeedTestPageSize = SpeedTestPageSize;
//_config.SpeedTestItem.SpeedTestPageSize = SpeedTestPageSize;
_config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl;
_config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl;
_config.GuiItem.EnableHWA = EnableHWA;

View File

@@ -259,11 +259,6 @@ namespace ServiceLib.ViewModels
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
}
private void UpdateSpeedtestHandler(SpeedTestResult result)
{
_updateView?.Invoke(EViewAction.DispatcherSpeedTest, result);
}
public void SetSpeedTestResult(SpeedTestResult result)
{
if (Utils.IsNullOrEmpty(result.IndexId))
@@ -272,7 +267,7 @@ namespace ServiceLib.ViewModels
NoticeHandler.Instance.Enqueue(result.Delay);
return;
}
var item = _profileItems.Where(it => it.IndexId == result.IndexId).FirstOrDefault();
var item = _profileItems.FirstOrDefault(it => it.IndexId == result.IndexId);
if (item != null)
{
if (Utils.IsNotEmpty(result.Delay))
@@ -293,7 +288,7 @@ namespace ServiceLib.ViewModels
{
try
{
var item = _profileItems.Where(it => it.IndexId == update.IndexId).FirstOrDefault();
var item = _profileItems.FirstOrDefault(it => it.IndexId == update.IndexId);
if (item != null)
{
item.TodayDown = Utils.HumanFy(update.TodayDown);
@@ -726,9 +721,11 @@ namespace ServiceLib.ViewModels
{
return;
}
//ClearTestResult();
_ = new SpeedtestService(_config, lstSelecteds, actionType, UpdateSpeedtestHandler);
_ = new SpeedtestService(_config, actionType, lstSelecteds, (SpeedTestResult result) =>
{
_updateView?.Invoke(EViewAction.DispatcherSpeedTest, result);
});
}
public void ServerSpeedtestStop()

View File

@@ -311,11 +311,11 @@ namespace ServiceLib.ViewModels
{
return;
}
await (new UpdateService()).RunAvailabilityCheck(async (bool success, string msg) =>
{
NoticeHandler.Instance.SendMessageEx(msg);
_updateView?.Invoke(EViewAction.DispatcherServerAvailability, msg);
});
var msg = await (new UpdateService()).RunAvailabilityCheck();
NoticeHandler.Instance.SendMessageEx(msg);
_updateView?.Invoke(EViewAction.DispatcherServerAvailability, msg);
}
public void TestServerAvailabilityResult(string msg)

View File

@@ -1,4 +1,4 @@
<Window
<Window
x:Class="v2rayN.Desktop.Views.OptionSettingWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -518,7 +518,7 @@
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyLinuxTip}"
TextWrapping="Wrap" />
<!--
<TextBlock
Grid.Row="16"
Grid.Column="0"
@@ -532,7 +532,7 @@
Width="200"
HorizontalAlignment="Left"
Classes="Margin8" />
-->
<TextBlock
Grid.Row="17"
Grid.Column="0"
@@ -896,4 +896,4 @@
</TabItem>
</TabControl>
</DockPanel>
</Window>
</Window>

View File

@@ -139,7 +139,7 @@ namespace v2rayN.Desktop.Views
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.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestPageSize, v => v.txtSpeedTestPageSize.Text).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.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);

View File

@@ -1,4 +1,4 @@
<reactiveui:ReactiveWindow
<reactiveui:ReactiveWindow
x:Class="v2rayN.Views.OptionSettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -776,7 +776,7 @@
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}"
TextWrapping="Wrap" />
<!--
<TextBlock
Grid.Row="16"
Grid.Column="0"
@@ -792,7 +792,7 @@
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
-->
<TextBlock
Grid.Row="17"
Grid.Column="0"
@@ -1197,4 +1197,4 @@
</TabItem>
</TabControl>
</DockPanel>
</reactiveui:ReactiveWindow>
</reactiveui:ReactiveWindow>

View File

@@ -150,7 +150,7 @@ namespace v2rayN.Views
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.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestPageSize, v => v.txtSpeedTestPageSize.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.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);