From d44f311ba15454b3af39bbe89a520f25c3e3ff03 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Sun, 19 Feb 2023 10:43:42 +0800 Subject: [PATCH] Refactoring sorting and delayed storage --- v2rayN/v2rayN/Handler/ConfigHandler.cs | 90 +++++++------- v2rayN/v2rayN/Handler/LazyConfig.cs | 36 +++--- v2rayN/v2rayN/Handler/ProfileExHandler.cs | 110 ++++++++++++++++++ v2rayN/v2rayN/Handler/SpeedtestHandler.cs | 28 ++--- v2rayN/v2rayN/Mode/ProfileExItem.cs | 14 +++ v2rayN/v2rayN/Mode/ProfileItem.cs | 9 -- v2rayN/v2rayN/Mode/ProfileItemModel.cs | 3 + .../v2rayN/ViewModels/MainWindowViewModel.cs | 23 ++-- 8 files changed, 217 insertions(+), 96 deletions(-) create mode 100644 v2rayN/v2rayN/Handler/ProfileExHandler.cs create mode 100644 v2rayN/v2rayN/Mode/ProfileExItem.cs diff --git a/v2rayN/v2rayN/Handler/ConfigHandler.cs b/v2rayN/v2rayN/Handler/ConfigHandler.cs index 0d32390c..b99f507f 100644 --- a/v2rayN/v2rayN/Handler/ConfigHandler.cs +++ b/v2rayN/v2rayN/Handler/ConfigHandler.cs @@ -438,14 +438,14 @@ namespace v2rayN.Handler /// /// /// - public static int SetDefaultServer(ref Config config, ProfileItem item) + public static int SetDefaultServerIndex(ref Config config, string indexId) { - if (item == null) + if (Utils.IsNullOrEmpty(indexId)) { return -1; } - config.indexId = item.indexId; + config.indexId = indexId; Global.reloadCore = true; ToJsonFile(config); @@ -453,24 +453,24 @@ namespace v2rayN.Handler return 0; } - public static int SetDefaultServer(Config config, List lstProfile) + public static int SetDefaultServer(Config config, List lstProfile) { if (lstProfile.Exists(t => t.indexId == config.indexId)) { return 0; } - - if (SqliteHelper.Instance.Table().Where(t => t.indexId == config.indexId).Count() > 0) + var allItems = LazyConfig.Instance.ProfileItemIndexs(""); + if (allItems.Where(t => t == config.indexId).Count() > 0) { return 0; } if (lstProfile.Count > 0) { - return SetDefaultServer(ref config, lstProfile[0]); + return SetDefaultServerIndex(ref config, lstProfile[0].indexId); } - if (SqliteHelper.Instance.Table().Count() > 0) + if (allItems.Count() > 0) { - return SetDefaultServer(ref config, SqliteHelper.Instance.Table().FirstOrDefault()); + return SetDefaultServerIndex(ref config, allItems.FirstOrDefault()); } return -1; } @@ -480,7 +480,7 @@ namespace v2rayN.Handler if (item is null) { var item2 = SqliteHelper.Instance.Table().FirstOrDefault(); - SetDefaultServer(ref config, item2); + SetDefaultServerIndex(ref config, item2?.indexId); return item2; } @@ -505,9 +505,10 @@ namespace v2rayN.Handler for (int i = 0; i < lstProfile.Count; i++) { - lstProfile[i].sort = (i + 1) * 10; + ProfileExHandler.Instance.SetSort(lstProfile[i].indexId, (i + 1) * 10); } + var sort = 0; switch (eMove) { case EMove.Top: @@ -516,7 +517,7 @@ namespace v2rayN.Handler { return 0; } - lstProfile[index].sort = lstProfile[0].sort - 1; + sort = ProfileExHandler.Instance.GetSort(lstProfile[0].indexId) - 1; break; } @@ -526,7 +527,7 @@ namespace v2rayN.Handler { return 0; } - lstProfile[index].sort = lstProfile[index - 1].sort - 1; + sort = ProfileExHandler.Instance.GetSort(lstProfile[index - 1].indexId) - 1; break; } @@ -537,7 +538,7 @@ namespace v2rayN.Handler { return 0; } - lstProfile[index].sort = lstProfile[index + 1].sort + 1; + sort = ProfileExHandler.Instance.GetSort(lstProfile[index + 1].indexId) + 1; break; } @@ -547,18 +548,16 @@ namespace v2rayN.Handler { return 0; } - lstProfile[index].sort = lstProfile[lstProfile.Count - 1].sort + 1; + sort = ProfileExHandler.Instance.GetSort(lstProfile[lstProfile.Count - 1].indexId) + 1; break; } case EMove.Position: - lstProfile[index].sort = pos * 10 + 1; + sort = pos * 10 + 1; break; } - SqliteHelper.Instance.UpdateAll(lstProfile); - - + ProfileExHandler.Instance.SetSort(lstProfile[index].indexId, sort); return 0; } @@ -698,11 +697,29 @@ namespace v2rayN.Handler public static int SortServers(ref Config config, string subId, EServerColName name, bool asc) { var lstModel = LazyConfig.Instance.ProfileItems(subId, ""); - var lstProfile = Utils.FromJson>(Utils.ToJson(lstModel)); - if (lstProfile.Count <= 0) + if (lstModel.Count <= 0) { return -1; } + var lstProfileExs = ProfileExHandler.Instance.ProfileExs; + var lstProfile = (from t in lstModel + join t3 in lstProfileExs on t.indexId equals t3.indexId into t3b + from t33 in t3b.DefaultIfEmpty() + select new ProfileItemModel + { + indexId = t.indexId, + configType = t.configType, + remarks = t.remarks, + address = t.address, + port = t.port, + security = t.security, + network = t.network, + streamSecurity = t.streamSecurity, + delay = t33 == null ? 0 : t33.delay, + speed = t33 == null ? 0 : t33.speed, + sort = t33 == null ? 0 : t33.sort + }).ToList(); + var propertyName = string.Empty; switch (name) { @@ -736,7 +753,7 @@ namespace v2rayN.Handler } for (int i = 0; i < lstProfile.Count; i++) { - lstProfile[i].sort = (i + 1) * 10; + ProfileExHandler.Instance.SetSort(lstProfile[i].indexId, (i + 1) * 10); } if (name == EServerColName.delay) { @@ -745,7 +762,7 @@ namespace v2rayN.Handler { if (item.delay <= 0) { - item.sort = maxSort; + ProfileExHandler.Instance.SetSort(item.indexId, maxSort); } } } @@ -756,13 +773,11 @@ namespace v2rayN.Handler { if (item.speed <= 0) { - item.sort = maxSort; + ProfileExHandler.Instance.SetSort(item.indexId, maxSort); } } } - SqliteHelper.Instance.UpdateAll(lstProfile); - return 0; } @@ -830,15 +845,8 @@ namespace v2rayN.Handler if (Utils.IsNullOrEmpty(profileItem.indexId)) { profileItem.indexId = Utils.GetGUID(false); - if (profileItem.sort <= 0) - { - var maxSort = 0; - if (SqliteHelper.Instance.Table().Count() > 0) - { - maxSort = SqliteHelper.Instance.Table().Max(t => t == null ? 0 : t.sort); - } - profileItem.sort = maxSort + 1; - } + var maxSort = ProfileExHandler.Instance.GetMaxSort(); + ProfileExHandler.Instance.SetSort(profileItem.indexId, maxSort + 1); } else if (profileItem.indexId == config.indexId) { @@ -929,11 +937,11 @@ namespace v2rayN.Handler } int countServers = 0; - var maxSort = 0; - if (SqliteHelper.Instance.Table().Count() > 0) - { - maxSort = SqliteHelper.Instance.Table().Max(t => t.sort); - } + //var maxSort = 0; + //if (SqliteHelper.Instance.Table().Count() > 0) + //{ + // maxSort = SqliteHelper.Instance.Table().Max(t => t.sort); + //} string[] arrData = clipboardData.Split(Environment.NewLine.ToCharArray()); foreach (string str in arrData) { @@ -971,7 +979,7 @@ namespace v2rayN.Handler } profileItem.subid = subid; profileItem.isSub = isSub; - profileItem.sort = maxSort + countServers + 1; + //profileItem.sort = maxSort + countServers + 1; if (profileItem.configType == EConfigType.VMess) { diff --git a/v2rayN/v2rayN/Handler/LazyConfig.cs b/v2rayN/v2rayN/Handler/LazyConfig.cs index 19ba0526..f1fe5093 100644 --- a/v2rayN/v2rayN/Handler/LazyConfig.cs +++ b/v2rayN/v2rayN/Handler/LazyConfig.cs @@ -17,6 +17,7 @@ namespace v2rayN.Handler SqliteHelper.Instance.CreateTable(); SqliteHelper.Instance.CreateTable(); SqliteHelper.Instance.CreateTable(); + SqliteHelper.Instance.CreateTable(); } #region Config @@ -81,6 +82,18 @@ namespace v2rayN.Handler return SqliteHelper.Instance.Table().Where(t => t.subid == subid).ToList(); } } + public List ProfileItemIndexs(string subid) + { + if (Utils.IsNullOrEmpty(subid)) + { + return SqliteHelper.Instance.Table().Select(t => t.indexId).ToList(); + + } + else + { + return SqliteHelper.Instance.Table().Where(t => t.subid == subid).Select(t => t.indexId).ToList(); + } + } public List ProfileItems(string subid, string filter) { @@ -101,7 +114,6 @@ namespace v2rayN.Handler } sql += $" and a.remarks like '%{filter}%'"; } - sql += " order by a.sort"; return SqliteHelper.Instance.Query(sql).ToList(); } @@ -115,28 +127,6 @@ namespace v2rayN.Handler return SqliteHelper.Instance.Table().FirstOrDefault(it => it.indexId == indexId); } - public Task SetTestResult(string indexId, string delayVal, string speedVal) - { - string sql = string.Empty; - if (!Utils.IsNullOrEmpty(delayVal) && !Utils.IsNullOrEmpty(speedVal)) - { - int.TryParse(delayVal, out int delay); - decimal.TryParse(speedVal, out decimal speed); - sql = $"update ProfileItem set delay={delay},speed={speed} where indexId = '{indexId}'"; - } - else if (!Utils.IsNullOrEmpty(delayVal)) - { - int.TryParse(delayVal, out int delay); - sql = $"update ProfileItem set delay={delay} where indexId = '{indexId}'"; - } - else if (!Utils.IsNullOrEmpty(speedVal)) - { - decimal.TryParse(speedVal, out decimal speed); - sql = $"update ProfileItem set speed={speed} where indexId = '{indexId}'"; - } - return SqliteHelper.Instance.ExecuteAsync(sql); - } - public List RoutingItems() { return SqliteHelper.Instance.Table().Where(it => it.locked == false).OrderBy(t => t.sort).ToList(); diff --git a/v2rayN/v2rayN/Handler/ProfileExHandler.cs b/v2rayN/v2rayN/Handler/ProfileExHandler.cs new file mode 100644 index 00000000..4d7b15c8 --- /dev/null +++ b/v2rayN/v2rayN/Handler/ProfileExHandler.cs @@ -0,0 +1,110 @@ +using v2rayN.Base; +using v2rayN.Mode; + +namespace v2rayN.Handler +{ + class ProfileExHandler + { + private static readonly Lazy _instance = new Lazy(() => new()); + private List _lstProfileEx; + public List ProfileExs => _lstProfileEx; + public static ProfileExHandler Instance => _instance.Value; + + public ProfileExHandler() + { + Init(); + } + + private void Init() + { + SqliteHelper.Instance.Execute($"delete from ProfileExItem where indexId not in ( select indexId from ProfileItem )"); + + _lstProfileEx = SqliteHelper.Instance.Table().ToList(); + } + + private void AddProfileEx(string indexId, ref ProfileExItem profileEx) + { + profileEx = new() + { + indexId = indexId, + delay = 0, + speed = 0, + sort = 0 + }; + _lstProfileEx.Add(profileEx); + SqliteHelper.Instance.Replace(profileEx); + } + + public void ClearAll() + { + SqliteHelper.Instance.Execute($"delete from ProfileExItem "); + _lstProfileEx = new(); + } + + public void SaveTo() + { + try + { + SqliteHelper.Instance.UpdateAll(_lstProfileEx); + } + catch (Exception ex) + { + Utils.SaveLog(ex.Message, ex); + } + } + + public Task SetTestDelay(string indexId, string delayVal) + { + var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId); + if (profileEx == null) + { + AddProfileEx(indexId, ref profileEx); + } + + int.TryParse(delayVal, out int delay); + profileEx.delay = delay; + return Task.CompletedTask; + } + + public Task SetTestSpeed(string indexId, string speedVal) + { + var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId); + if (profileEx == null) + { + AddProfileEx(indexId, ref profileEx); + } + + decimal.TryParse(speedVal, out decimal speed); + profileEx.speed = speed; + return Task.CompletedTask; + } + + public void SetSort(string indexId, int sort) + { + var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId); + if (profileEx == null) + { + AddProfileEx(indexId, ref profileEx); + } + profileEx.sort = sort; + } + + public int GetSort(string indexId) + { + var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId); + if (profileEx == null) + { + return 0; + } + return profileEx.sort; + } + public int GetMaxSort() + { + if (_lstProfileEx.Count <= 0) + { + return 0; + } + return _lstProfileEx.Max(t => t == null ? 0 : t.sort); + } + } +} diff --git a/v2rayN/v2rayN/Handler/SpeedtestHandler.cs b/v2rayN/v2rayN/Handler/SpeedtestHandler.cs index 711b67dc..531780f3 100644 --- a/v2rayN/v2rayN/Handler/SpeedtestHandler.cs +++ b/v2rayN/v2rayN/Handler/SpeedtestHandler.cs @@ -112,24 +112,24 @@ namespace v2rayN.Handler private void RunPing() { - RunPingSub((ServerTestItem it) => + RunPingSub(async (ServerTestItem it) => { long time = Ping(it.address); var output = FormatOut(time, Global.DelayUnit); - LazyConfig.Instance.SetTestResult(it.indexId, output, ""); + await ProfileExHandler.Instance.SetTestDelay(it.indexId, output); UpdateFunc(it.indexId, output); }); } private void RunTcping() { - RunPingSub((ServerTestItem it) => + RunPingSub(async (ServerTestItem it) => { int time = GetTcpingTime(it.address, it.port); var output = FormatOut(time, Global.DelayUnit); - LazyConfig.Instance.SetTestResult(it.indexId, output, ""); + await ProfileExHandler.Instance.SetTestDelay(it.indexId, output); UpdateFunc(it.indexId, output); }); } @@ -161,16 +161,15 @@ namespace v2rayN.Handler { continue; } - tasks.Add(Task.Run(() => + tasks.Add(Task.Run(async () => { try { - LazyConfig.Instance.SetTestResult(it.indexId, "-1", ""); WebProxy webProxy = new WebProxy(Global.Loopback, it.port); string output = GetRealPingTime(downloadHandle, webProxy); - LazyConfig.Instance.SetTestResult(it.indexId, output, ""); + await ProfileExHandler.Instance.SetTestDelay(it.indexId, output); UpdateFunc(it.indexId, output); int.TryParse(output, out int delay); it.delay = delay; @@ -191,6 +190,7 @@ namespace v2rayN.Handler finally { if (pid > 0) _coreHandler.CoreStopPid(pid); + ProfileExHandler.Instance.SaveTo(); } return Task.CompletedTask; @@ -231,19 +231,19 @@ namespace v2rayN.Handler // UpdateFunc(it.indexId, "", ResUI.SpeedtestingSkip); // continue; //} - _ = LazyConfig.Instance.SetTestResult(it.indexId, "", "-1"); + await ProfileExHandler.Instance.SetTestSpeed(it.indexId, "-1"); var item = LazyConfig.Instance.GetProfileItem(it.indexId); if (item is null) continue; WebProxy webProxy = new WebProxy(Global.Loopback, it.port); - await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (bool success, string msg) => + await downloadHandle.DownloadDataAsync(url, webProxy, timeout, async (bool success, string msg) => { decimal.TryParse(msg, out decimal dec); if (dec > 0) { - _ = LazyConfig.Instance.SetTestResult(it.indexId, "", msg); + await ProfileExHandler.Instance.SetTestSpeed(it.indexId, msg); } UpdateFunc(it.indexId, "", msg); }); @@ -254,6 +254,7 @@ namespace v2rayN.Handler _coreHandler.CoreStopPid(pid); } UpdateFunc("", ResUI.SpeedtestingCompleted); + ProfileExHandler.Instance.SaveTo(); } private async Task RunSpeedTestMulti() @@ -281,18 +282,18 @@ namespace v2rayN.Handler { continue; } - _ = LazyConfig.Instance.SetTestResult(it.indexId, "", "-1"); + await ProfileExHandler.Instance.SetTestSpeed(it.indexId, "-1"); var item = LazyConfig.Instance.GetProfileItem(it.indexId); if (item is null) continue; WebProxy webProxy = new WebProxy(Global.Loopback, it.port); - _ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (bool success, string msg) => + _ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, async (bool success, string msg) => { decimal.TryParse(msg, out decimal dec); if (dec > 0) { - _ = LazyConfig.Instance.SetTestResult(it.indexId, "", msg); + await ProfileExHandler.Instance.SetTestSpeed(it.indexId, msg); } UpdateFunc(it.indexId, "", msg); }); @@ -306,6 +307,7 @@ namespace v2rayN.Handler _coreHandler.CoreStopPid(pid); } UpdateFunc("", ResUI.SpeedtestingCompleted); + ProfileExHandler.Instance.SaveTo(); } private async Task RunMixedtestAsync() diff --git a/v2rayN/v2rayN/Mode/ProfileExItem.cs b/v2rayN/v2rayN/Mode/ProfileExItem.cs new file mode 100644 index 00000000..6cbd341a --- /dev/null +++ b/v2rayN/v2rayN/Mode/ProfileExItem.cs @@ -0,0 +1,14 @@ +using SQLite; + +namespace v2rayN.Mode +{ + [Serializable] + public class ProfileExItem + { + [PrimaryKey] + public string indexId { get; set; } + public int delay { get; set; } + public decimal speed { get; set; } + public int sort { get; set; } + } +} diff --git a/v2rayN/v2rayN/Mode/ProfileItem.cs b/v2rayN/v2rayN/Mode/ProfileItem.cs index 00ce76c1..f043dc4f 100644 --- a/v2rayN/v2rayN/Mode/ProfileItem.cs +++ b/v2rayN/v2rayN/Mode/ProfileItem.cs @@ -11,7 +11,6 @@ namespace v2rayN.Mode indexId = string.Empty; configType = EConfigType.VMess; configVersion = 2; - sort = 0; address = string.Empty; port = 0; id = string.Empty; @@ -107,11 +106,6 @@ namespace v2rayN.Mode get; set; } - public int sort - { - get; set; - } - /// /// 远程服务器地址 /// @@ -202,9 +196,6 @@ namespace v2rayN.Mode get; set; } - public int delay { get; set; } - public decimal speed { get; set; } - /// /// SubItem id /// diff --git a/v2rayN/v2rayN/Mode/ProfileItemModel.cs b/v2rayN/v2rayN/Mode/ProfileItemModel.cs index 096bb71c..c183a3f5 100644 --- a/v2rayN/v2rayN/Mode/ProfileItemModel.cs +++ b/v2rayN/v2rayN/Mode/ProfileItemModel.cs @@ -5,6 +5,9 @@ { public bool isActive { get; set; } public string subRemarks { get; set; } + public int delay { get; set; } + public decimal speed { get; set; } + public int sort { get; set; } public string delayVal { get; set; } public string speedVal { get; set; } public string todayUp { get; set; } diff --git a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs index c829e412..e8a687ad 100644 --- a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs @@ -664,6 +664,8 @@ namespace v2rayN.ViewModels SysProxyHandle.UpdateSysProxy(_config, true); } + ProfileExHandler.Instance.SaveTo(); + _statistics?.SaveTo(); _statistics?.Close(); @@ -708,19 +710,19 @@ namespace v2rayN.ViewModels private void RefreshServers() { List lstModel = LazyConfig.Instance.ProfileItems(_subId, _serverFilter); - _lstProfile = Utils.FromJson>(Utils.ToJson(lstModel)); - - ConfigHandler.SetDefaultServer(_config, _lstProfile); + ConfigHandler.SetDefaultServer(_config, lstModel); List lstServerStat = new(); if (_statistics != null && _statistics.Enable) { lstServerStat = _statistics.ServerStat; } + var lstProfileExs = ProfileExHandler.Instance.ProfileExs; lstModel = (from t in lstModel - join t2 in lstServerStat - on t.indexId equals t2.indexId into t2b + join t2 in lstServerStat on t.indexId equals t2.indexId into t2b from t22 in t2b.DefaultIfEmpty() + join t3 in lstProfileExs on t.indexId equals t3.indexId into t3b + from t33 in t3b.DefaultIfEmpty() select new ProfileItemModel { indexId = t.indexId, @@ -733,14 +735,15 @@ namespace v2rayN.ViewModels streamSecurity = t.streamSecurity, subRemarks = t.subRemarks, isActive = t.indexId == _config.indexId, - delay = t.delay, - delayVal = t.delay != 0 ? $"{t.delay} {Global.DelayUnit}" : string.Empty, - speedVal = t.speed != 0 ? $"{t.speed} {Global.SpeedUnit}" : string.Empty, + sort = t33 == null ? 0 : t33.sort, + delayVal = t33?.delay != 0 ? $"{t33?.delay} {Global.DelayUnit}" : string.Empty, + speedVal = t33?.speed != 0 ? $"{t33?.speed} {Global.SpeedUnit}" : string.Empty, todayDown = t22 == null ? "" : Utils.HumanFy(t22.todayDown), todayUp = t22 == null ? "" : Utils.HumanFy(t22.todayUp), totalDown = t22 == null ? "" : Utils.HumanFy(t22.totalDown), totalUp = t22 == null ? "" : Utils.HumanFy(t22.totalUp) - }).ToList(); + }).OrderBy(t => t.sort).ToList(); + _lstProfile = Utils.FromJson>(Utils.ToJson(lstModel)); Application.Current.Dispatcher.Invoke((Action)(() => { @@ -982,7 +985,7 @@ namespace v2rayN.ViewModels return; } - if (ConfigHandler.SetDefaultServer(ref _config, item) == 0) + if (ConfigHandler.SetDefaultServerIndex(ref _config, indexId) == 0) { RefreshServers(); Reload();