Refactoring sorting and delayed storage

pull/3309/head
2dust 2023-02-19 10:43:42 +08:00
parent 6f5428ca61
commit d44f311ba1
8 changed files with 217 additions and 96 deletions

View File

@ -438,14 +438,14 @@ namespace v2rayN.Handler
/// <param name="config"></param>
/// <param name="item"></param>
/// <returns></returns>
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<ProfileItem> lstProfile)
public static int SetDefaultServer(Config config, List<ProfileItemModel> lstProfile)
{
if (lstProfile.Exists(t => t.indexId == config.indexId))
{
return 0;
}
if (SqliteHelper.Instance.Table<ProfileItem>().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<ProfileItem>().Count() > 0)
if (allItems.Count() > 0)
{
return SetDefaultServer(ref config, SqliteHelper.Instance.Table<ProfileItem>().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<ProfileItem>().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<List<ProfileItem>>(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<ProfileItem>().Count() > 0)
{
maxSort = SqliteHelper.Instance.Table<ProfileItem>().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<ProfileItem>().Count() > 0)
{
maxSort = SqliteHelper.Instance.Table<ProfileItem>().Max(t => t.sort);
}
//var maxSort = 0;
//if (SqliteHelper.Instance.Table<ProfileItem>().Count() > 0)
//{
// maxSort = SqliteHelper.Instance.Table<ProfileItem>().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)
{

View File

@ -17,6 +17,7 @@ namespace v2rayN.Handler
SqliteHelper.Instance.CreateTable<ProfileItem>();
SqliteHelper.Instance.CreateTable<ServerStatItem>();
SqliteHelper.Instance.CreateTable<RoutingItem>();
SqliteHelper.Instance.CreateTable<ProfileExItem>();
}
#region Config
@ -81,6 +82,18 @@ namespace v2rayN.Handler
return SqliteHelper.Instance.Table<ProfileItem>().Where(t => t.subid == subid).ToList();
}
}
public List<string> ProfileItemIndexs(string subid)
{
if (Utils.IsNullOrEmpty(subid))
{
return SqliteHelper.Instance.Table<ProfileItem>().Select(t => t.indexId).ToList();
}
else
{
return SqliteHelper.Instance.Table<ProfileItem>().Where(t => t.subid == subid).Select(t => t.indexId).ToList();
}
}
public List<ProfileItemModel> 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<ProfileItemModel>(sql).ToList();
}
@ -115,28 +127,6 @@ namespace v2rayN.Handler
return SqliteHelper.Instance.Table<ProfileItem>().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<RoutingItem> RoutingItems()
{
return SqliteHelper.Instance.Table<RoutingItem>().Where(it => it.locked == false).OrderBy(t => t.sort).ToList();

View File

@ -0,0 +1,110 @@
using v2rayN.Base;
using v2rayN.Mode;
namespace v2rayN.Handler
{
class ProfileExHandler
{
private static readonly Lazy<ProfileExHandler> _instance = new Lazy<ProfileExHandler>(() => new());
private List<ProfileExItem> _lstProfileEx;
public List<ProfileExItem> 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<ProfileExItem>().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);
}
}
}

View File

@ -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()

View File

@ -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; }
}
}

View File

@ -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;
}
/// <summary>
/// 远程服务器地址
/// </summary>
@ -202,9 +196,6 @@ namespace v2rayN.Mode
get; set;
}
public int delay { get; set; }
public decimal speed { get; set; }
/// <summary>
/// SubItem id
/// </summary>

View File

@ -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; }

View File

@ -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<ProfileItemModel> lstModel = LazyConfig.Instance.ProfileItems(_subId, _serverFilter);
_lstProfile = Utils.FromJson<List<ProfileItem>>(Utils.ToJson(lstModel));
ConfigHandler.SetDefaultServer(_config, _lstProfile);
ConfigHandler.SetDefaultServer(_config, lstModel);
List<ServerStatItem> 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<List<ProfileItem>>(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();