mirror of
https://github.com/2dust/v2rayN.git
synced 2025-08-29 22:36:20 +00:00
v1.1
Signed-off-by: lazycat75246 <153997642+lazycat75246@users.noreply.github.com>
This commit is contained in:
parent
6f864701e0
commit
48f4ecc472
14 changed files with 512 additions and 49 deletions
|
@ -1,4 +1,4 @@
|
|||
using v2rayN.Base;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
using v2rayN.Mode;
|
||||
|
||||
namespace v2rayN.Handler
|
||||
|
@ -176,6 +176,15 @@ namespace v2rayN.Handler
|
|||
return SqliteHelper.Instance.Table<ProfileItem>().FirstOrDefault(it => it.indexId == indexId);
|
||||
}
|
||||
|
||||
public ProfileItem? GetProfileItemRemarks(string Remarks)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(Remarks))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return SqliteHelper.Instance.Table<ProfileItem>().FirstOrDefault(it => it.remarks == Remarks);
|
||||
}
|
||||
|
||||
public ProfileItem? GetProfileItemViaRemarks(string remarks)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(remarks))
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
using DynamicData;
|
||||
using Splat;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using v2rayN.Mode;
|
||||
using v2rayN.Resx;
|
||||
using v2rayN.ViewModels;
|
||||
|
||||
namespace v2rayN.Handler
|
||||
{
|
||||
public delegate void SetDefaultServerDelegate(string s);
|
||||
public delegate void SetTestResultDelegate(string i, string d, string s);
|
||||
public class TestResultItem
|
||||
{
|
||||
public string indexId { get; set; }
|
||||
|
@ -24,6 +29,8 @@ namespace v2rayN.Handler
|
|||
private NoticeHandler? _noticeHandler;
|
||||
private Task taskmain = null;
|
||||
private SetDefaultServerDelegate setDefaultServerDelegates;
|
||||
private SetTestResultDelegate setTestResultDelegates;
|
||||
private SetAutoSwitchTogDelegate _setAutoSwitchTog;
|
||||
public ServerAutoSwitch()
|
||||
{
|
||||
|
||||
|
@ -36,12 +43,20 @@ namespace v2rayN.Handler
|
|||
{
|
||||
bStop = true;
|
||||
if(taskmain!=null)
|
||||
taskmain.Wait();
|
||||
taskmain.Wait();
|
||||
taskmain = null;
|
||||
}
|
||||
public void SetDelegate(SetDefaultServerDelegate s = null) {
|
||||
this.setDefaultServerDelegates = s;
|
||||
}
|
||||
public void SetDelegate(SetTestResultDelegate s = null)
|
||||
{
|
||||
this.setTestResultDelegates = s;
|
||||
}
|
||||
public void SetDelegate(SetAutoSwitchTogDelegate s = null)
|
||||
{
|
||||
this._setAutoSwitchTog = s;
|
||||
}
|
||||
private void UpdateHandler(bool notify, string msg)
|
||||
{
|
||||
}
|
||||
|
@ -62,6 +77,7 @@ namespace v2rayN.Handler
|
|||
indexId = id,
|
||||
latency = i
|
||||
});
|
||||
setTestResultDelegates(id, dl, speed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,56 +93,114 @@ namespace v2rayN.Handler
|
|||
|
||||
taskmain = Task.Run(() =>
|
||||
{
|
||||
int iFailTimeMax = 30;
|
||||
int iTestInterval = iFailTimeMax / 3;
|
||||
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
|
||||
DownloadHandle downloadHandle = new();
|
||||
long failtimestart = 0;
|
||||
int LastServerSelectMode = -1;
|
||||
List<ProfileItem> listprofile = new List<ProfileItem>();
|
||||
while (!bStop)
|
||||
{
|
||||
var _config = LazyConfig.Instance.GetConfig();
|
||||
int iFailTimeMax = LazyConfig.Instance.GetConfig().autoSwitchItem.FailTimeMax;
|
||||
int iTestInterval = iFailTimeMax / 3;
|
||||
int ServerSelectMode = LazyConfig.Instance.GetConfig().autoSwitchItem.ServerSelectMode;
|
||||
int AutoSwitchMode = LazyConfig.Instance.GetConfig().autoSwitchItem.mode;
|
||||
|
||||
Thread.Sleep(iTestInterval * 1000);
|
||||
int res = downloadHandle.RunAvailabilityCheck(null).Result;
|
||||
if (!bStop)
|
||||
Task.Run(() => setTestResultDelegates(_config.indexId, res.ToString(), ""));
|
||||
else
|
||||
break;
|
||||
if (res <= 0)
|
||||
{
|
||||
_noticeHandler?.SendMessage("Current server test failed!", true);
|
||||
_noticeHandler?.SendMessage("Current server test failed!",true);
|
||||
if (failtimestart == 0)
|
||||
failtimestart = GetTimestamp(DateTime.Now);
|
||||
if (GetTimestamp(DateTime.Now) - failtimestart >= iFailTimeMax)
|
||||
{
|
||||
if (testResultItems.Count == 0 || listprofile.Count == 0)
|
||||
listprofile = LazyConfig.Instance.ProfileItemsAutoSwitch();
|
||||
if (listprofile.Count > 0)
|
||||
if (testResultItems.Count == 0 || listprofile.Count == 0 || ServerSelectMode!= LastServerSelectMode)
|
||||
{
|
||||
var _config = LazyConfig.Instance.GetConfig();
|
||||
testResultItems.Clear();
|
||||
listprofile = LazyConfig.Instance.ProfileItemsAutoSwitch();
|
||||
}
|
||||
|
||||
if (listprofile.Count >= 2)
|
||||
{
|
||||
|
||||
if (testResultItems.Count == 0)
|
||||
{
|
||||
var _coreHandler = new CoreHandler(_config, (bool x, string y) => { });
|
||||
new SpeedtestHandler(_config, _coreHandler, listprofile, Mode.ESpeedActionType.Tcping, UpdateSpeedtestHandler);
|
||||
while (testResultItems.Count < listprofile.Count)
|
||||
|
||||
if (ServerSelectMode == 0 || ServerSelectMode == 1)
|
||||
new SpeedtestHandler(_config, _coreHandler, listprofile, Mode.ESpeedActionType.Tcping, UpdateSpeedtestHandler);
|
||||
else if (ServerSelectMode == 2)
|
||||
new SpeedtestHandler(_config, _coreHandler, listprofile, Mode.ESpeedActionType.Realping, UpdateSpeedtestHandler);
|
||||
if (bStop) break;
|
||||
while (!bStop && testResultItems.Count < listprofile.Count)
|
||||
{
|
||||
Thread.Sleep(20);
|
||||
}
|
||||
}
|
||||
if (bStop) break;
|
||||
if (ServerSelectMode == 0)
|
||||
{
|
||||
List<TestResultItem> templist = new List<TestResultItem>();
|
||||
|
||||
for(int i=testResultItems.Count-1; i>=0; i--) {
|
||||
if (testResultItems[i].latency <= 0 || testResultItems[i].indexId == _config.indexId)
|
||||
testResultItems.RemoveAt(i);
|
||||
foreach (var item in listprofile)
|
||||
{
|
||||
var item2 = testResultItems.Find(x => x.indexId == item.indexId);
|
||||
if (item2 != null)
|
||||
templist.Add(item2);
|
||||
}
|
||||
testResultItems = templist;
|
||||
}
|
||||
}
|
||||
|
||||
if (testResultItems.Count > 0)
|
||||
if (ServerSelectMode == 0)
|
||||
{
|
||||
testResultItems.Sort((x, y) => x.latency.CompareTo(y.latency));
|
||||
setDefaultServerDelegates(testResultItems[0].indexId);
|
||||
//if (ConfigHandler.SetDefaultServerIndex(ref _config, testResultItems[0].indexId) == 0)
|
||||
//{
|
||||
// RefreshServers();
|
||||
// Reload();
|
||||
//}
|
||||
|
||||
testResultItems.RemoveAt(0);
|
||||
for (int i = testResultItems.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (testResultItems[i].latency <= 0 && testResultItems[i].indexId != _config.indexId)
|
||||
testResultItems.RemoveAt(i);
|
||||
}
|
||||
if (testResultItems.Count > 1)
|
||||
{
|
||||
int j = testResultItems.FindIndex(x => x.indexId == _config.indexId);
|
||||
int k = j + 1;
|
||||
if (k > testResultItems.Count - 1)
|
||||
k = 0;
|
||||
setDefaultServerDelegates(testResultItems[k].indexId);
|
||||
testResultItems.RemoveAt(j);
|
||||
if (testResultItems.Count <= 1)
|
||||
testResultItems.Clear();
|
||||
}
|
||||
else
|
||||
testResultItems.Clear();
|
||||
|
||||
}
|
||||
else if (ServerSelectMode == 1 || ServerSelectMode == 2)
|
||||
{
|
||||
for (int i = testResultItems.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (testResultItems[i].latency <= 0 || testResultItems[i].indexId == _config.indexId)
|
||||
testResultItems.RemoveAt(i);
|
||||
}
|
||||
|
||||
if (testResultItems.Count > 0)
|
||||
{
|
||||
testResultItems.Sort((x, y) => x.latency.CompareTo(y.latency));
|
||||
setDefaultServerDelegates(testResultItems[0].indexId);
|
||||
testResultItems.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_setAutoSwitchTog(false);
|
||||
_config.autoSwitchItem.EnableAutoSwitch = false;
|
||||
MessageBox.Show(ResUI.stopSwtichWarn);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -135,7 +209,7 @@ namespace v2rayN.Handler
|
|||
testResultItems.Clear();
|
||||
listprofile.Clear();
|
||||
}
|
||||
|
||||
LastServerSelectMode = ServerSelectMode;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -167,6 +167,7 @@ namespace v2rayN.Handler
|
|||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var listprofile = LazyConfig.Instance.ProfileItemsAutoSwitch();
|
||||
foreach (var item in subItem)
|
||||
{
|
||||
string id = item.id.TrimEx();
|
||||
|
@ -275,6 +276,16 @@ namespace v2rayN.Handler
|
|||
Logging.SaveLog("FailedImportSubscription");
|
||||
Logging.SaveLog(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item3 in listprofile)
|
||||
{
|
||||
var item2 = LazyConfig.Instance.GetProfileItemRemarks(item3.remarks);
|
||||
item2.autoSwitch = true;
|
||||
SqliteHelper.Instance.Update(item2);
|
||||
}
|
||||
ConfigHandler.SaveConfig(_config);
|
||||
}
|
||||
_updateFunc(false,
|
||||
ret > 0
|
||||
? $"{hashCode}{ResUI.MsgUpdateSubscriptionEnd}"
|
||||
|
@ -284,6 +295,8 @@ namespace v2rayN.Handler
|
|||
}
|
||||
|
||||
_updateFunc(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
54
v2rayN/v2rayN/Resx/ResUI.Designer.cs
generated
54
v2rayN/v2rayN/Resx/ResUI.Designer.cs
generated
|
@ -1815,6 +1815,15 @@ namespace v2rayN.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Because the number of selected switching servers is less than the minimum value of 2, stop automatic switching! 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string stopSwtichWarn {
|
||||
get {
|
||||
return ResourceManager.GetString("stopSwtichWarn", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Group please leave blank here 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@ -2770,6 +2779,24 @@ namespace v2rayN.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Lowest RealPing Latency Server 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLowestRealPingServer {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsLowestRealPingServer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Lowest TCPing Latency Server 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLowestTCPingServer {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsLowestTCPingServer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 sing-box Mux Protocol 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@ -2806,6 +2833,15 @@ namespace v2rayN.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Next Server 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsNextServer {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsNextServer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Auth pass 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@ -2833,6 +2869,15 @@ namespace v2rayN.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Switch when server cannot connect 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsServerFail {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsServerFail", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Switch to server 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@ -3292,6 +3337,15 @@ namespace v2rayN.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 The number of selected switching servers must be greater than or equal to 2 to start switching! 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string turnOnSwitchWarn {
|
||||
get {
|
||||
return ResourceManager.GetString("turnOnSwitchWarn", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Ungrouped 的本地化字符串。
|
||||
/// </summary>
|
||||
|
|
|
@ -1162,4 +1162,22 @@
|
|||
<data name="TbSettingsUseSystemHosts" xml:space="preserve">
|
||||
<value>از هاست های سیستم استفاده کنید</value>
|
||||
</data>
|
||||
<data name="TbSettingsNextServer" xml:space="preserve">
|
||||
<value>سرور بعدی</value>
|
||||
</data>
|
||||
<data name="TbSettingsLowestTCPingServer" xml:space="preserve">
|
||||
<value>سرور با کمترین تاخیر TCPing</value>
|
||||
</data>
|
||||
<data name="TbSettingsLowestRealPingServer" xml:space="preserve">
|
||||
<value>کمترین سرور RealPing Latency</value>
|
||||
</data>
|
||||
<data name="TbSettingsServerFail" xml:space="preserve">
|
||||
<value>هنگامی که سرور نمی تواند متصل شود، تغییر دهید</value>
|
||||
</data>
|
||||
<data name="stopSwtichWarn" xml:space="preserve">
|
||||
<value>از آنجایی که تعداد سرورهای سوئیچینگ انتخابی کمتر از مقدار حداقل 2 است، تعویض خودکار را متوقف کنید!</value>
|
||||
</data>
|
||||
<data name="turnOnSwitchWarn" xml:space="preserve">
|
||||
<value>برای شروع سوئیچینگ، تعداد سرورهای سوئیچینگ انتخابی باید بیشتر یا مساوی 2 باشد!</value>
|
||||
</data>
|
||||
</root>
|
|
@ -205,7 +205,7 @@
|
|||
<value>Type</value>
|
||||
</data>
|
||||
<data name="LvAutoSwitch" xml:space="preserve">
|
||||
<value>AutoSwitch</value>
|
||||
<value>AutoSwitch</value>
|
||||
</data>
|
||||
<data name="LvSubscription" xml:space="preserve">
|
||||
<value>Subs group</value>
|
||||
|
@ -1198,4 +1198,22 @@
|
|||
<data name="TbLocalAddress" xml:space="preserve">
|
||||
<value>Address(Ip,Ipv6)</value>
|
||||
</data>
|
||||
<data name="TbSettingsNextServer" xml:space="preserve">
|
||||
<value>Next Server</value>
|
||||
</data>
|
||||
<data name="TbSettingsLowestTCPingServer" xml:space="preserve">
|
||||
<value>Lowest TCPing Latency Server</value>
|
||||
</data>
|
||||
<data name="TbSettingsLowestRealPingServer" xml:space="preserve">
|
||||
<value>Lowest RealPing Latency Server</value>
|
||||
</data>
|
||||
<data name="TbSettingsServerFail" xml:space="preserve">
|
||||
<value>Switch when server cannot connect</value>
|
||||
</data>
|
||||
<data name="stopSwtichWarn" xml:space="preserve">
|
||||
<value>Because the number of selected switching servers is less than the minimum value of 2, stop automatic switching!</value>
|
||||
</data>
|
||||
<data name="turnOnSwitchWarn" xml:space="preserve">
|
||||
<value>The number of selected switching servers must be greater than or equal to 2 to start switching!</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1162,4 +1162,22 @@
|
|||
<data name="TbSettingsUseSystemHosts" xml:space="preserve">
|
||||
<value>Используйте системные хосты</value>
|
||||
</data>
|
||||
<data name="TbSettingsNextServer" xml:space="preserve">
|
||||
<value>Следующий сервер</value>
|
||||
</data>
|
||||
<data name="TbSettingsLowestTCPingServer" xml:space="preserve">
|
||||
<value>Сервер с наименьшей задержкой TCPing</value>
|
||||
</data>
|
||||
<data name="TbSettingsLowestRealPingServer" xml:space="preserve">
|
||||
<value>Сервер с самой низкой задержкой RealPing</value>
|
||||
</data>
|
||||
<data name="TbSettingsServerFail" xml:space="preserve">
|
||||
<value>Переключиться, когда сервер не может подключиться</value>
|
||||
</data>
|
||||
<data name="stopSwtichWarn" xml:space="preserve">
|
||||
<value>Поскольку количество выбранных коммутационных серверов меньше минимального значения 2, остановите автоматическое переключение!</value>
|
||||
</data>
|
||||
<data name="turnOnSwitchWarn" xml:space="preserve">
|
||||
<value>Для начала переключения количество выбранных коммутационных серверов должно быть больше или равно 2!</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1195,4 +1195,22 @@
|
|||
<data name="TbLocalAddress" xml:space="preserve">
|
||||
<value>Address(Ip,Ipv6)</value>
|
||||
</data>
|
||||
<data name="TbSettingsNextServer" xml:space="preserve">
|
||||
<value>下一个服务器</value>
|
||||
</data>
|
||||
<data name="TbSettingsLowestTCPingServer" xml:space="preserve">
|
||||
<value>最低TCPing延迟服务器</value>
|
||||
</data>
|
||||
<data name="TbSettingsLowestRealPingServer" xml:space="preserve">
|
||||
<value>最低真连接延迟服务器</value>
|
||||
</data>
|
||||
<data name="TbSettingsServerFail" xml:space="preserve">
|
||||
<value>服务器无法连接时切换</value>
|
||||
</data>
|
||||
<data name="stopSwtichWarn" xml:space="preserve">
|
||||
<value>因为选择的切换服务器数量小于最低值2,停止自动切换!</value>
|
||||
</data>
|
||||
<data name="turnOnSwitchWarn" xml:space="preserve">
|
||||
<value>选择的切换服务器数量必须大于等于2才能启动切换!</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1136,7 +1136,7 @@
|
|||
<value>IP 或 IP CIDR</value>
|
||||
</data>
|
||||
<data name="LvAutoSwitch" xml:space="preserve">
|
||||
<value>自動切換</value>
|
||||
<value>切換</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoSwitch" xml:space="preserve">
|
||||
<value>自動切換設定</value>
|
||||
|
@ -1180,4 +1180,22 @@
|
|||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||
<value>啟用IPv6</value>
|
||||
</data>
|
||||
<data name="TbSettingsNextServer" xml:space="preserve">
|
||||
<value>下一个服务器</value>
|
||||
</data>
|
||||
<data name="TbSettingsLowestTCPingServer" xml:space="preserve">
|
||||
<value>TCPing 延遲最低的伺服器</value>
|
||||
</data>
|
||||
<data name="TbSettingsLowestRealPingServer" xml:space="preserve">
|
||||
<value>最低 RealPing 延遲伺服器</value>
|
||||
</data>
|
||||
<data name="TbSettingsServerFail" xml:space="preserve">
|
||||
<value>伺服器無法連接時切換</value>
|
||||
</data>
|
||||
<data name="stopSwtichWarn" xml:space="preserve">
|
||||
<value>由於選擇的切換伺服器數量小於最小值2,因此停止自動切換!</value>
|
||||
</data>
|
||||
<data name="turnOnSwitchWarn" xml:space="preserve">
|
||||
<value>選定的切換伺服器數量必須大於或等於2才能開始切換!</value>
|
||||
</data>
|
||||
</root>
|
|
@ -13,6 +13,7 @@ using System.Reactive;
|
|||
using System.Reactive.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using v2rayN.Handler;
|
||||
using v2rayN.Mode;
|
||||
|
@ -22,6 +23,7 @@ using v2rayN.Views;
|
|||
namespace v2rayN.ViewModels
|
||||
{
|
||||
public delegate void SetAutoSwitchTogDelegate(bool b);
|
||||
public delegate void SetAutoSwitchAllDelegate(bool b);
|
||||
public class MainWindowViewModel : ReactiveObject
|
||||
{
|
||||
#region private prop
|
||||
|
@ -37,10 +39,15 @@ namespace v2rayN.ViewModels
|
|||
private Dictionary<string, bool> _dicHeaderSort = new();
|
||||
private Action<EViewAction> _updateView;
|
||||
private SetAutoSwitchTogDelegate _setAutoSwitchTog;
|
||||
private SetAutoSwitchAllDelegate _setAutoSwitchAll;
|
||||
public void SetDelegate(SetAutoSwitchTogDelegate s = null)
|
||||
{
|
||||
this._setAutoSwitchTog = s;
|
||||
}
|
||||
public void SetDelegate2(SetAutoSwitchAllDelegate s = null)
|
||||
{
|
||||
this._setAutoSwitchAll = s;
|
||||
}
|
||||
#endregion private prop
|
||||
|
||||
#region ObservableCollection
|
||||
|
@ -254,9 +261,12 @@ namespace v2rayN.ViewModels
|
|||
[Reactive]
|
||||
public string CurrentLanguage { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool autoSwitchCheckAll { get; set; }
|
||||
|
||||
#endregion UI
|
||||
|
||||
|
||||
|
||||
|
||||
public ServerAutoSwitch ServerAutoSwitchs= new ServerAutoSwitch();
|
||||
|
||||
|
@ -605,7 +615,9 @@ namespace v2rayN.ViewModels
|
|||
Reload();
|
||||
ChangeSystemProxyStatus(_config.sysProxyType, true);
|
||||
ServerAutoSwitchs.SetDelegate(SetDefaultServer);
|
||||
if(_config.autoSwitchItem.EnableAutoSwitch)
|
||||
ServerAutoSwitchs.SetDelegate(UpdateSpeedtestHandler);
|
||||
ServerAutoSwitchs.SetDelegate(_setAutoSwitchTog);
|
||||
if (_config.autoSwitchItem.EnableAutoSwitch)
|
||||
ServerAutoSwitchs.Start();
|
||||
}
|
||||
|
||||
|
@ -614,7 +626,7 @@ namespace v2rayN.ViewModels
|
|||
Application.Current.Dispatcher.Invoke((Action)(() =>
|
||||
{
|
||||
ShowHideWindow(true);
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
#endregion Init
|
||||
|
@ -757,9 +769,9 @@ namespace v2rayN.ViewModels
|
|||
{
|
||||
Logging.SaveLog("MyAppExit Begin");
|
||||
|
||||
StorageUI();
|
||||
StorageUI();
|
||||
ConfigHandler.SaveConfig(_config);
|
||||
|
||||
ServerAutoSwitchs.Stop();
|
||||
//HttpProxyHandle.CloseHttpAgent(config);
|
||||
if (blWindowsShutDown)
|
||||
{
|
||||
|
@ -891,6 +903,16 @@ namespace v2rayN.ViewModels
|
|||
RunningServerDisplay = ResUI.CheckServerSettings;
|
||||
RunningServerToolTipText = ResUI.CheckServerSettings;
|
||||
}
|
||||
|
||||
int autoswitchservercount = 0;
|
||||
foreach (var item in lstModel)
|
||||
{
|
||||
if(item.autoSwitch)
|
||||
autoswitchservercount++;
|
||||
}
|
||||
|
||||
if(_setAutoSwitchAll!=null)
|
||||
_setAutoSwitchAll( lstModel.Count>0 && autoswitchservercount == lstModel.Count);
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -1668,11 +1690,11 @@ namespace v2rayN.ViewModels
|
|||
var profiles = LazyConfig.Instance.ProfileItemsAutoSwitch();
|
||||
if (profiles.Count < 2)
|
||||
{
|
||||
MessageBox.Show("选择的切换服务器必须大于等于2才能启动切换!");
|
||||
MessageBox.Show(ResUI.turnOnSwitchWarn);
|
||||
_setAutoSwitchTog(false);
|
||||
_config.autoSwitchItem.EnableAutoSwitch = false;
|
||||
EnableAutoSwitch = false;
|
||||
ConfigHandler.SaveConfig(ref _config);
|
||||
ConfigHandler.SaveConfig(_config);
|
||||
return;
|
||||
}
|
||||
ServerAutoSwitchs.Start();
|
||||
|
@ -1684,7 +1706,7 @@ namespace v2rayN.ViewModels
|
|||
ServerAutoSwitchs.Stop();
|
||||
});
|
||||
}
|
||||
ConfigHandler.SaveConfig(ref _config);
|
||||
ConfigHandler.SaveConfig(_config);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1899,18 +1921,18 @@ namespace v2rayN.ViewModels
|
|||
|
||||
private void AutoHideStartup()
|
||||
{
|
||||
if (_config.uiItem.autoHideStartup)
|
||||
{
|
||||
|
||||
Observable.Range(1, 1)
|
||||
.Delay(TimeSpan.FromSeconds(0.5))
|
||||
.Subscribe(x =>
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
ShowHideWindow(false);
|
||||
ShowHideWindow(!_config.uiItem.autoHideStartup);
|
||||
RefreshServers();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion UI
|
||||
|
|
|
@ -99,6 +99,10 @@ namespace v2rayN.ViewModels
|
|||
|
||||
#endregion CoreType
|
||||
|
||||
[Reactive] public int ServerSelectMode { get; set; }
|
||||
[Reactive] public int AutoSwitchMode { get; set; }
|
||||
[Reactive] public int FailTimeMax { get; set; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SaveCmd { get; }
|
||||
|
||||
public OptionSettingViewModel(Window view)
|
||||
|
@ -181,6 +185,10 @@ namespace v2rayN.ViewModels
|
|||
|
||||
#endregion Tun mode
|
||||
|
||||
FailTimeMax = _config.autoSwitchItem.FailTimeMax;
|
||||
AutoSwitchMode = _config.autoSwitchItem.mode;
|
||||
ServerSelectMode = _config.autoSwitchItem.ServerSelectMode;
|
||||
|
||||
InitCoreType();
|
||||
|
||||
SaveCmd = ReactiveCommand.Create(() =>
|
||||
|
@ -326,6 +334,10 @@ namespace v2rayN.ViewModels
|
|||
_config.tunModeItem.enableExInbound = TunEnableExInbound;
|
||||
_config.tunModeItem.enableIPv6Address = TunEnableIPv6Address;
|
||||
|
||||
_config.autoSwitchItem.mode = AutoSwitchMode;
|
||||
_config.autoSwitchItem.ServerSelectMode=ServerSelectMode;
|
||||
_config.autoSwitchItem.FailTimeMax = FailTimeMax;
|
||||
|
||||
//coreType
|
||||
SaveCoreType();
|
||||
|
||||
|
|
|
@ -674,10 +674,16 @@
|
|||
</DataGrid.Resources>
|
||||
<DataGrid.Columns>
|
||||
<base:MyDGBoolColumn
|
||||
x:Name="autoSwitchCheckCol"
|
||||
Width="Auto"
|
||||
Binding="{Binding autoSwitch, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
ExName="autoSwitch"
|
||||
Header="{x:Static resx:ResUI.LvAutoSwitch}">
|
||||
<DataGridCheckBoxColumn.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<CheckBox Name="autoSwitchCheckAll" Content="{x:Static resx:ResUI.LvAutoSwitch}" Click="AutoSwitchAll_Click"/>
|
||||
</DataTemplate>
|
||||
</DataGridCheckBoxColumn.HeaderTemplate>
|
||||
<DataGridCheckBoxColumn.ElementStyle>
|
||||
<Style TargetType="CheckBox">
|
||||
<Setter Property= "HorizontalAlignment" Value= "Center" />
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using ReactiveUI;
|
||||
using Splat;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
@ -61,6 +62,12 @@ namespace v2rayN.Views
|
|||
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
|
||||
|
||||
ViewModel.SetDelegate((bool b)=> togEnableAutoSwitch.IsChecked = b);
|
||||
ViewModel.SetDelegate2((bool b) =>
|
||||
{
|
||||
var autoswitchcheckbox = FindVisualChild<CheckBox>(lstProfiles, "autoSwitchCheckAll");
|
||||
if(autoswitchcheckbox != null)
|
||||
autoswitchcheckbox.IsChecked = b;
|
||||
});
|
||||
|
||||
for (int i = Global.MinFontSize; i <= Global.MinFontSize + 8; i++)
|
||||
{
|
||||
|
@ -208,8 +215,9 @@ namespace v2rayN.Views
|
|||
this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables);
|
||||
|
||||
});
|
||||
|
||||
|
||||
RestoreUI();
|
||||
AddHelpMenuItem();
|
||||
|
||||
|
@ -312,9 +320,10 @@ namespace v2rayN.Views
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var colName = ((MyDGTextColumn)colHeader.Column).ExName;
|
||||
ViewModel?.SortServer(colName);
|
||||
var colHeader2 = colHeader.Column as MyDGTextColumn;
|
||||
var colName = colHeader2==null ? "" : colHeader2.ExName;
|
||||
if(colName != "")
|
||||
ViewModel?.SortServer(colName);
|
||||
}
|
||||
|
||||
private void menuSelectAll_Click(object sender, RoutedEventArgs e)
|
||||
|
@ -481,13 +490,27 @@ namespace v2rayN.Views
|
|||
}
|
||||
|
||||
var lvColumnItem = _config.uiItem.mainColumnItem.OrderBy(t => t.Index).ToList();
|
||||
if(lvColumnItem.FindIndex(t=>t.Name== "autoSwitch")==-1)
|
||||
{
|
||||
lvColumnItem.Insert(0,new()
|
||||
{
|
||||
Name = "autoSwitch",
|
||||
Width = 79,
|
||||
Index = 0
|
||||
});
|
||||
for(var p=0;p<lvColumnItem.Count;p++)
|
||||
{
|
||||
lvColumnItem[p].Index = p;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < lvColumnItem.Count; i++)
|
||||
{
|
||||
var item = lvColumnItem[i];
|
||||
for (int k = 0; k < lstProfiles.Columns.Count; k++)
|
||||
{
|
||||
var item2 = (MyDGTextColumn)lstProfiles.Columns[k];
|
||||
if (item2.ExName == item.Name)
|
||||
var item2 = lstProfiles.Columns[k] as MyDGTextColumn;
|
||||
|
||||
if(item2 != null && item2.ExName == item.Name)
|
||||
{
|
||||
if (item.Width < 0)
|
||||
{
|
||||
|
@ -499,6 +522,23 @@ namespace v2rayN.Views
|
|||
item2.DisplayIndex = i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var item3 = lstProfiles.Columns[k] as MyDGBoolColumn;
|
||||
if (item3 != null && item3.ExName == item.Name)
|
||||
{
|
||||
if (item.Width < 0)
|
||||
{
|
||||
item3.Visibility = Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
item3.Width = item.Width;
|
||||
item3.DisplayIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,13 +566,25 @@ namespace v2rayN.Views
|
|||
List<ColumnItem> lvColumnItem = new();
|
||||
for (int k = 0; k < lstProfiles.Columns.Count; k++)
|
||||
{
|
||||
var item2 = (MyDGTextColumn)lstProfiles.Columns[k];
|
||||
var item2 = lstProfiles.Columns[k] as MyDGTextColumn;
|
||||
if(item2!=null)
|
||||
lvColumnItem.Add(new()
|
||||
{
|
||||
Name = item2.ExName,
|
||||
Width = item2.Visibility == Visibility.Visible ? Convert.ToInt32(item2.ActualWidth) : -1,
|
||||
Index = item2.DisplayIndex
|
||||
});
|
||||
else
|
||||
{
|
||||
var item3 = lstProfiles.Columns[k] as MyDGBoolColumn;
|
||||
if (item3 != null)
|
||||
lvColumnItem.Add(new()
|
||||
{
|
||||
Name = item3.ExName,
|
||||
Width = item3.Visibility == Visibility.Visible ? Convert.ToInt32(item3.ActualWidth) : -1,
|
||||
Index = item3.DisplayIndex
|
||||
});
|
||||
}
|
||||
}
|
||||
_config.uiItem.mainColumnItem = lvColumnItem;
|
||||
|
||||
|
@ -566,12 +618,108 @@ namespace v2rayN.Views
|
|||
Utils.ProcessStart(item.Tag.ToString());
|
||||
}
|
||||
}
|
||||
private void AutoSwitchAll_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CheckBox cb = sender as CheckBox;
|
||||
foreach (var item in ViewModel.ProfileItems)
|
||||
{
|
||||
item.autoSwitch = cb.IsChecked ?? item.autoSwitch;
|
||||
var item2 = LazyConfig.Instance.GetProfileItem(item.indexId);
|
||||
if(item2.autoSwitch != item.autoSwitch)
|
||||
{
|
||||
item2.autoSwitch = item.autoSwitch;
|
||||
SqliteHelper.Instance.Update(item2);
|
||||
}
|
||||
}
|
||||
|
||||
ViewModel.RefreshServers();
|
||||
var profiles = LazyConfig.Instance.ProfileItemsAutoSwitch();
|
||||
if (profiles.Count < 2 && _config.autoSwitchItem.EnableAutoSwitch)
|
||||
{
|
||||
togEnableAutoSwitch.IsChecked = false;
|
||||
_config.autoSwitchItem.EnableAutoSwitch = false;
|
||||
MessageBox.Show(ResUI.stopSwtichWarn);
|
||||
}
|
||||
}
|
||||
private T FindVisualChild<T>(DependencyObject obj,string name = null)
|
||||
where T : DependencyObject
|
||||
{
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
||||
{
|
||||
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
||||
var currChildElement = child as FrameworkElement;
|
||||
if (child != null && child is T)
|
||||
{
|
||||
if(string.IsNullOrEmpty(name) == false && currChildElement.Name == name)
|
||||
return (T)child;
|
||||
}
|
||||
else
|
||||
{
|
||||
T childOfChild = FindVisualChild<T>(child,name);
|
||||
if (childOfChild != null)
|
||||
return childOfChild;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static T GetVisualChild<T>(DependencyObject parent,
|
||||
string name = null) where T : DependencyObject
|
||||
{
|
||||
T result;
|
||||
int count;
|
||||
DependencyObject currChild;
|
||||
FrameworkElement currChildElement;
|
||||
|
||||
count = VisualTreeHelper.GetChildrenCount(parent);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
currChild = VisualTreeHelper.GetChild(parent, i);
|
||||
currChildElement = currChild as FrameworkElement;
|
||||
|
||||
if (currChild is T)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name) == false)
|
||||
{
|
||||
// A name was given so the child must match it
|
||||
if ((currChildElement != null) &&
|
||||
(currChildElement.Name == name))
|
||||
{
|
||||
return ((T)currChild);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No name was given but the type matches
|
||||
return ((T)currChild);
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively search children
|
||||
result = GetVisualChild<T>(currChild, name);
|
||||
if (result != null)
|
||||
{
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
return (null);
|
||||
}
|
||||
private void AutoSwitch_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//CheckBox cb = sender as CheckBox;
|
||||
var item = LazyConfig.Instance.GetProfileItem(ViewModel.SelectedProfile.indexId);
|
||||
item.autoSwitch = ViewModel.SelectedProfile.autoSwitch;
|
||||
SqliteHelper.Instance.Update(item);
|
||||
if(!ViewModel.SelectedProfile.autoSwitch)
|
||||
{
|
||||
var profiles = LazyConfig.Instance.ProfileItemsAutoSwitch();
|
||||
if(profiles.Count< 2 && _config.autoSwitchItem.EnableAutoSwitch)
|
||||
{
|
||||
togEnableAutoSwitch.IsChecked = false;
|
||||
_config.autoSwitchItem.EnableAutoSwitch = false;
|
||||
MessageBox.Show(ResUI.stopSwtichWarn);
|
||||
}
|
||||
}
|
||||
//if(ViewModel.EnableAutoSwitch)
|
||||
//{
|
||||
// ViewModel.ServerAutoSwitchs.Start();
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Timers;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using v2rayN.Handler;
|
||||
using v2rayN.Mode;
|
||||
|
@ -85,6 +87,11 @@ namespace v2rayN.Views
|
|||
cmbSubConvertUrl.Items.Add(it);
|
||||
});
|
||||
|
||||
cmbServerSelectMode.Items.Add(Resx.ResUI.TbSettingsNextServer);
|
||||
cmbServerSelectMode.Items.Add(Resx.ResUI.TbSettingsLowestTCPingServer);
|
||||
cmbServerSelectMode.Items.Add(Resx.ResUI.TbSettingsLowestRealPingServer);
|
||||
|
||||
cmbAutoSwitchMainMode.Items.Add(Resx.ResUI.TbSettingsServerFail);
|
||||
//fill fonts
|
||||
try
|
||||
{
|
||||
|
@ -195,10 +202,38 @@ namespace v2rayN.Views
|
|||
this.Bind(ViewModel, vm => vm.CoreType5, v => v.cmbCoreType5.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CoreType6, v => v.cmbCoreType6.Text).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.AutoSwitchMode, v => v.cmbAutoSwitchMainMode.SelectedIndex).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.ServerSelectMode, v => v.cmbServerSelectMode.SelectedIndex).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FailTimeMax, v => v.txtFailTimeMax.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
txtFailTimeMax.TextChanged += (s, e) =>
|
||||
{
|
||||
txtFailTimeMax_OnTextChanged(s, e);
|
||||
};
|
||||
}
|
||||
private async void txtFailTimeMax_OnTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (sender is TextBox tb)
|
||||
{
|
||||
string beginContext = tb.Text;
|
||||
await Task.Delay(2000);
|
||||
if (beginContext == tb.Text)
|
||||
{
|
||||
int value;
|
||||
if (int.TryParse(tb.Text, out value))
|
||||
{
|
||||
if (value > 600)
|
||||
tb.Text = "600";
|
||||
else if (value < 30)
|
||||
tb.Text = "30";
|
||||
}
|
||||
ViewModel.FailTimeMax=value;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void btnCancel_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
|
|
Loading…
Reference in a new issue