mirror of https://github.com/2dust/v2rayN
Refactor code to decouple view and viewmodel
parent
a9860418ba
commit
7faabdc375
|
@ -4,6 +4,7 @@
|
||||||
{
|
{
|
||||||
CloseWindow,
|
CloseWindow,
|
||||||
ShowYesNo,
|
ShowYesNo,
|
||||||
|
SaveFileDialog,
|
||||||
AddBatchRoutingRulesYesNo,
|
AddBatchRoutingRulesYesNo,
|
||||||
AdjustMainLvColWidth,
|
AdjustMainLvColWidth,
|
||||||
ProfilesFocus,
|
ProfilesFocus,
|
||||||
|
|
|
@ -355,13 +355,64 @@ namespace v2rayN.Handler
|
||||||
|
|
||||||
#region Server
|
#region Server
|
||||||
|
|
||||||
|
public static int AddServer(Config config, ProfileItem profileItem)
|
||||||
|
{
|
||||||
|
var item = LazyConfig.Instance.GetProfileItem(profileItem.indexId);
|
||||||
|
if (item is null)
|
||||||
|
{
|
||||||
|
item = profileItem;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.coreType = profileItem.coreType;
|
||||||
|
item.remarks = profileItem.remarks;
|
||||||
|
item.address = profileItem.address;
|
||||||
|
item.port = profileItem.port;
|
||||||
|
|
||||||
|
item.id = profileItem.id;
|
||||||
|
item.alterId = profileItem.alterId;
|
||||||
|
item.security = profileItem.security;
|
||||||
|
item.flow = profileItem.flow;
|
||||||
|
|
||||||
|
item.network = profileItem.network;
|
||||||
|
item.headerType = profileItem.headerType;
|
||||||
|
item.requestHost = profileItem.requestHost;
|
||||||
|
item.path = profileItem.path;
|
||||||
|
|
||||||
|
item.streamSecurity = profileItem.streamSecurity;
|
||||||
|
item.sni = profileItem.sni;
|
||||||
|
item.allowInsecure = profileItem.allowInsecure;
|
||||||
|
item.fingerprint = profileItem.fingerprint;
|
||||||
|
item.alpn = profileItem.alpn;
|
||||||
|
|
||||||
|
item.publicKey = profileItem.publicKey;
|
||||||
|
item.shortId = profileItem.shortId;
|
||||||
|
item.spiderX = profileItem.spiderX;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret = item.configType switch
|
||||||
|
{
|
||||||
|
EConfigType.VMess => AddVMessServer(config, item),
|
||||||
|
EConfigType.Shadowsocks => AddShadowsocksServer(config, item),
|
||||||
|
EConfigType.Socks => AddSocksServer(config, item),
|
||||||
|
EConfigType.Http => AddHttpServer(config, item),
|
||||||
|
EConfigType.Trojan => AddTrojanServer(config, item),
|
||||||
|
EConfigType.VLESS => AddVlessServer(config, item),
|
||||||
|
EConfigType.Hysteria2 => AddHysteria2Server(config, item),
|
||||||
|
EConfigType.Tuic => AddTuicServer(config, item),
|
||||||
|
EConfigType.Wireguard => AddWireguardServer(config, item),
|
||||||
|
_ => -1,
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add or edit server
|
/// Add or edit server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="config"></param>
|
/// <param name="config"></param>
|
||||||
/// <param name="profileItem"></param>
|
/// <param name="profileItem"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static int AddServer(Config config, ProfileItem profileItem, bool toFile = true)
|
public static int AddVMessServer(Config config, ProfileItem profileItem, bool toFile = true)
|
||||||
{
|
{
|
||||||
profileItem.configType = EConfigType.VMess;
|
profileItem.configType = EConfigType.VMess;
|
||||||
|
|
||||||
|
@ -619,7 +670,21 @@ namespace v2rayN.Handler
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static int EditCustomServer(Config config, ProfileItem profileItem)
|
public static int EditCustomServer(Config config, ProfileItem profileItem)
|
||||||
{
|
{
|
||||||
if (SQLiteHelper.Instance.Update(profileItem) > 0)
|
var item = LazyConfig.Instance.GetProfileItem(profileItem.indexId);
|
||||||
|
if (item is null)
|
||||||
|
{
|
||||||
|
item = profileItem;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.remarks = profileItem.remarks;
|
||||||
|
item.address = profileItem.address;
|
||||||
|
item.coreType = profileItem.coreType;
|
||||||
|
item.displayLog = profileItem.displayLog;
|
||||||
|
item.preSocksPort = profileItem.preSocksPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SQLiteHelper.Instance.Update(item) > 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1189,7 +1254,7 @@ namespace v2rayN.Handler
|
||||||
|
|
||||||
var addStatus = profileItem.configType switch
|
var addStatus = profileItem.configType switch
|
||||||
{
|
{
|
||||||
EConfigType.VMess => AddServer(config, profileItem, false),
|
EConfigType.VMess => AddVMessServer(config, profileItem, false),
|
||||||
EConfigType.Shadowsocks => AddShadowsocksServer(config, profileItem, false),
|
EConfigType.Shadowsocks => AddShadowsocksServer(config, profileItem, false),
|
||||||
EConfigType.Socks => AddSocksServer(config, profileItem, false),
|
EConfigType.Socks => AddSocksServer(config, profileItem, false),
|
||||||
EConfigType.Trojan => AddTrojanServer(config, profileItem, false),
|
EConfigType.Trojan => AddTrojanServer(config, profileItem, false),
|
||||||
|
@ -1419,21 +1484,41 @@ namespace v2rayN.Handler
|
||||||
|
|
||||||
public static int AddSubItem(Config config, SubItem subItem)
|
public static int AddSubItem(Config config, SubItem subItem)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(subItem.id))
|
var item = LazyConfig.Instance.GetSubItem(subItem.id);
|
||||||
|
if (item is null)
|
||||||
{
|
{
|
||||||
subItem.id = Utils.GetGUID(false);
|
item = subItem;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.remarks = subItem.remarks;
|
||||||
|
item.url = subItem.url;
|
||||||
|
item.moreUrl = subItem.moreUrl;
|
||||||
|
item.enabled = subItem.enabled;
|
||||||
|
item.autoUpdateInterval = subItem.autoUpdateInterval;
|
||||||
|
item.userAgent = subItem.userAgent;
|
||||||
|
item.sort = subItem.sort;
|
||||||
|
item.filter = subItem.filter;
|
||||||
|
item.convertTarget = subItem.convertTarget;
|
||||||
|
item.prevProfile = subItem.prevProfile;
|
||||||
|
item.nextProfile = subItem.nextProfile;
|
||||||
|
}
|
||||||
|
|
||||||
if (subItem.sort <= 0)
|
if (Utils.IsNullOrEmpty(item.id))
|
||||||
|
{
|
||||||
|
item.id = Utils.GetGUID(false);
|
||||||
|
|
||||||
|
if (item.sort <= 0)
|
||||||
{
|
{
|
||||||
var maxSort = 0;
|
var maxSort = 0;
|
||||||
if (SQLiteHelper.Instance.Table<SubItem>().Count() > 0)
|
if (SQLiteHelper.Instance.Table<SubItem>().Count() > 0)
|
||||||
{
|
{
|
||||||
maxSort = SQLiteHelper.Instance.Table<SubItem>().Max(t => t == null ? 0 : t.sort);
|
maxSort = SQLiteHelper.Instance.Table<SubItem>().Max(t => t == null ? 0 : t.sort);
|
||||||
}
|
}
|
||||||
subItem.sort = maxSort + 1;
|
item.sort = maxSort + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (SQLiteHelper.Instance.Replace(subItem) > 0)
|
if (SQLiteHelper.Instance.Replace(item) > 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using v2rayN.Enums;
|
using v2rayN.Enums;
|
||||||
|
using v2rayN.Handler.Statistics;
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler
|
||||||
|
@ -119,6 +120,45 @@ namespace v2rayN.Handler
|
||||||
return SQLiteHelper.Instance.Query<ProfileItemModel>(sql).ToList();
|
return SQLiteHelper.Instance.Query<ProfileItemModel>(sql).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ProfileItemModel> ProfileItemsEx(string subid, string filter)
|
||||||
|
{
|
||||||
|
var lstModel = ProfileItems(_config.subIndexId, filter);
|
||||||
|
|
||||||
|
ConfigHandler.SetDefaultServer(_config, lstModel);
|
||||||
|
|
||||||
|
var lstServerStat = (_config.guiItem.enableStatistics ? StatisticsHandler.Instance.ServerStat : null) ?? [];
|
||||||
|
var lstProfileExs = ProfileExHandler.Instance.ProfileExs;
|
||||||
|
lstModel = (from t in lstModel
|
||||||
|
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,
|
||||||
|
configType = t.configType,
|
||||||
|
remarks = t.remarks,
|
||||||
|
address = t.address,
|
||||||
|
port = t.port,
|
||||||
|
security = t.security,
|
||||||
|
network = t.network,
|
||||||
|
streamSecurity = t.streamSecurity,
|
||||||
|
subid = t.subid,
|
||||||
|
subRemarks = t.subRemarks,
|
||||||
|
isActive = t.indexId == _config.indexId,
|
||||||
|
sort = t33 == null ? 0 : t33.sort,
|
||||||
|
delay = t33 == null ? 0 : t33.delay,
|
||||||
|
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)
|
||||||
|
}).OrderBy(t => t.sort).ToList();
|
||||||
|
|
||||||
|
return lstModel;
|
||||||
|
}
|
||||||
|
|
||||||
public ProfileItem? GetProfileItem(string indexId)
|
public ProfileItem? GetProfileItem(string indexId)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(indexId))
|
if (Utils.IsNullOrEmpty(indexId))
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
using v2rayN.Models;
|
||||||
|
|
||||||
|
namespace v2rayN.Handler
|
||||||
|
{
|
||||||
|
internal class TaskHandler
|
||||||
|
{
|
||||||
|
private static readonly Lazy<TaskHandler> _instance = new(() => new());
|
||||||
|
public static TaskHandler Instance => _instance.Value;
|
||||||
|
|
||||||
|
public TaskHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegUpdateTask(Config config, Action<bool, string> update)
|
||||||
|
{
|
||||||
|
Task.Run(() => UpdateTaskRunSubscription(config, update));
|
||||||
|
Task.Run(() => UpdateTaskRunGeo(config, update));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateTaskRunSubscription(Config config, Action<bool, string> update)
|
||||||
|
{
|
||||||
|
await Task.Delay(60000);
|
||||||
|
Logging.SaveLog("UpdateTaskRunSubscription");
|
||||||
|
|
||||||
|
var updateHandle = new UpdateHandler();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var updateTime = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds();
|
||||||
|
var lstSubs = LazyConfig.Instance.SubItems()
|
||||||
|
.Where(t => t.autoUpdateInterval > 0)
|
||||||
|
.Where(t => updateTime - t.updateTime >= t.autoUpdateInterval * 60)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var item in lstSubs)
|
||||||
|
{
|
||||||
|
updateHandle.UpdateSubscriptionProcess(config, item.id, true, (bool success, string msg) =>
|
||||||
|
{
|
||||||
|
update(success, msg);
|
||||||
|
if (success)
|
||||||
|
Logging.SaveLog("subscription" + msg);
|
||||||
|
});
|
||||||
|
item.updateTime = updateTime;
|
||||||
|
ConfigHandler.AddSubItem(config, item);
|
||||||
|
|
||||||
|
await Task.Delay(5000);
|
||||||
|
}
|
||||||
|
await Task.Delay(60000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateTaskRunGeo(Config config, Action<bool, string> update)
|
||||||
|
{
|
||||||
|
var autoUpdateGeoTime = DateTime.Now;
|
||||||
|
|
||||||
|
await Task.Delay(1000 * 120);
|
||||||
|
Logging.SaveLog("UpdateTaskRunGeo");
|
||||||
|
|
||||||
|
var updateHandle = new UpdateHandler();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var dtNow = DateTime.Now;
|
||||||
|
if (config.guiItem.autoUpdateInterval > 0)
|
||||||
|
{
|
||||||
|
if ((dtNow - autoUpdateGeoTime).Hours % config.guiItem.autoUpdateInterval == 0)
|
||||||
|
{
|
||||||
|
updateHandle.UpdateGeoFileAll(config, (bool success, string msg) =>
|
||||||
|
{
|
||||||
|
update(false, msg);
|
||||||
|
});
|
||||||
|
autoUpdateGeoTime = dtNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(1000 * 3600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +1,15 @@
|
||||||
using Microsoft.Win32;
|
using System.Drawing;
|
||||||
using Splat;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Interop;
|
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using v2rayN.Enums;
|
using v2rayN.Enums;
|
||||||
using v2rayN.Handler.CoreConfig;
|
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
|
||||||
|
|
||||||
namespace v2rayN.Handler
|
namespace v2rayN.Handler
|
||||||
{
|
{
|
||||||
public sealed class MainFormHandler
|
public sealed class WindowsHandler
|
||||||
{
|
{
|
||||||
private static readonly Lazy<MainFormHandler> instance = new(() => new());
|
private static readonly Lazy<WindowsHandler> instance = new(() => new());
|
||||||
public static MainFormHandler Instance => instance.Value;
|
public static WindowsHandler Instance => instance.Value;
|
||||||
|
|
||||||
public Icon GetNotifyIcon(Config config)
|
public Icon GetNotifyIcon(Config config)
|
||||||
{
|
{
|
||||||
|
@ -123,66 +116,11 @@ namespace v2rayN.Handler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Export2ClientConfig(ProfileItem item, Config config)
|
|
||||||
{
|
|
||||||
if (item == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SaveFileDialog fileDialog = new()
|
|
||||||
{
|
|
||||||
Filter = "Config|*.json",
|
|
||||||
FilterIndex = 2,
|
|
||||||
RestoreDirectory = true
|
|
||||||
};
|
|
||||||
if (fileDialog.ShowDialog() != true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
string fileName = fileDialog.FileName;
|
|
||||||
if (Utils.IsNullOrEmpty(fileName))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (CoreConfigHandler.GenerateClientConfig(item, fileName, out string msg, out string content) != 0)
|
|
||||||
{
|
|
||||||
Locator.Current.GetService<NoticeHandler>()?.Enqueue(msg);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg = string.Format(ResUI.SaveClientConfigurationIn, fileName);
|
|
||||||
Locator.Current.GetService<NoticeHandler>()?.SendMessageAndEnqueue(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RegisterGlobalHotkey(Config config, Action<EGlobalHotkey> handler, Action<bool, string>? update)
|
public void RegisterGlobalHotkey(Config config, Action<EGlobalHotkey> handler, Action<bool, string>? update)
|
||||||
{
|
{
|
||||||
HotkeyHandler.Instance.UpdateViewEvent += update;
|
HotkeyHandler.Instance.UpdateViewEvent += update;
|
||||||
HotkeyHandler.Instance.HotkeyTriggerEvent += handler;
|
HotkeyHandler.Instance.HotkeyTriggerEvent += handler;
|
||||||
HotkeyHandler.Instance.Load();
|
HotkeyHandler.Instance.Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterSystemColorSet(Config config, Window window, Action<bool> update)
|
|
||||||
{
|
|
||||||
var helper = new WindowInteropHelper(window);
|
|
||||||
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
|
|
||||||
hwndSource.AddHook((IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) =>
|
|
||||||
{
|
|
||||||
if (config.uiItem.followSystemTheme)
|
|
||||||
{
|
|
||||||
const int WM_SETTINGCHANGE = 0x001A;
|
|
||||||
if (msg == WM_SETTINGCHANGE)
|
|
||||||
{
|
|
||||||
if (wParam == IntPtr.Zero && Marshal.PtrToStringUni(lParam) == "ImmersiveColorSet")
|
|
||||||
{
|
|
||||||
update(!WindowsUtils.IsLightTheme());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return IntPtr.Zero;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -67,21 +67,7 @@ namespace v2rayN.ViewModels
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = LazyConfig.Instance.GetProfileItem(SelectedSource.indexId);
|
if (ConfigHandler.EditCustomServer(_config, SelectedSource) == 0)
|
||||||
if (item is null)
|
|
||||||
{
|
|
||||||
item = SelectedSource;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item.remarks = SelectedSource.remarks;
|
|
||||||
item.address = SelectedSource.address;
|
|
||||||
item.coreType = SelectedSource.coreType;
|
|
||||||
item.displayLog = SelectedSource.displayLog;
|
|
||||||
item.preSocksPort = SelectedSource.preSocksPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ConfigHandler.EditCustomServer(_config, item) == 0)
|
|
||||||
{
|
{
|
||||||
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
||||||
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||||
|
|
|
@ -85,54 +85,7 @@ namespace v2rayN.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = LazyConfig.Instance.GetProfileItem(SelectedSource.indexId);
|
if (ConfigHandler.AddServer(_config, SelectedSource) == 0)
|
||||||
if (item is null)
|
|
||||||
{
|
|
||||||
item = SelectedSource;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item.coreType = SelectedSource.coreType;
|
|
||||||
item.remarks = SelectedSource.remarks;
|
|
||||||
item.address = SelectedSource.address;
|
|
||||||
item.port = SelectedSource.port;
|
|
||||||
|
|
||||||
item.id = SelectedSource.id;
|
|
||||||
item.alterId = SelectedSource.alterId;
|
|
||||||
item.security = SelectedSource.security;
|
|
||||||
item.flow = SelectedSource.flow;
|
|
||||||
|
|
||||||
item.network = SelectedSource.network;
|
|
||||||
item.headerType = SelectedSource.headerType;
|
|
||||||
item.requestHost = SelectedSource.requestHost;
|
|
||||||
item.path = SelectedSource.path;
|
|
||||||
|
|
||||||
item.streamSecurity = SelectedSource.streamSecurity;
|
|
||||||
item.sni = SelectedSource.sni;
|
|
||||||
item.allowInsecure = SelectedSource.allowInsecure;
|
|
||||||
item.fingerprint = SelectedSource.fingerprint;
|
|
||||||
item.alpn = SelectedSource.alpn;
|
|
||||||
|
|
||||||
item.publicKey = SelectedSource.publicKey;
|
|
||||||
item.shortId = SelectedSource.shortId;
|
|
||||||
item.spiderX = SelectedSource.spiderX;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ret = item.configType switch
|
|
||||||
{
|
|
||||||
EConfigType.VMess => ConfigHandler.AddServer(_config, item),
|
|
||||||
EConfigType.Shadowsocks => ConfigHandler.AddShadowsocksServer(_config, item),
|
|
||||||
EConfigType.Socks => ConfigHandler.AddSocksServer(_config, item),
|
|
||||||
EConfigType.Http => ConfigHandler.AddHttpServer(_config, item),
|
|
||||||
EConfigType.Trojan => ConfigHandler.AddTrojanServer(_config, item),
|
|
||||||
EConfigType.VLESS => ConfigHandler.AddVlessServer(_config, item),
|
|
||||||
EConfigType.Hysteria2 => ConfigHandler.AddHysteria2Server(_config, item),
|
|
||||||
EConfigType.Tuic => ConfigHandler.AddTuicServer(_config, item),
|
|
||||||
EConfigType.Wireguard => ConfigHandler.AddWireguardServer(_config, item),
|
|
||||||
_ => -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ret == 0)
|
|
||||||
{
|
{
|
||||||
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
||||||
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||||
|
|
|
@ -162,8 +162,10 @@ namespace v2rayN.ViewModels
|
||||||
|
|
||||||
if (mode != ERuleMode.Unchanged)
|
if (mode != ERuleMode.Unchanged)
|
||||||
{
|
{
|
||||||
Dictionary<string, string> headers = new Dictionary<string, string>();
|
Dictionary<string, string> headers = new()
|
||||||
headers.Add("mode", mode.ToString().ToLower());
|
{
|
||||||
|
{ "mode", mode.ToString().ToLower() }
|
||||||
|
};
|
||||||
ClashApiHandler.Instance.ClashConfigUpdate(headers);
|
ClashApiHandler.Instance.ClashConfigUpdate(headers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,15 +384,10 @@ namespace v2rayN.ViewModels
|
||||||
_proxyGroups.Replace(group, group2);
|
_proxyGroups.Replace(group, group2);
|
||||||
|
|
||||||
SelectedGroup = group2;
|
SelectedGroup = group2;
|
||||||
|
|
||||||
//var index = _proxyGroups.IndexOf(group);
|
|
||||||
//_proxyGroups.Remove(group);
|
|
||||||
//_proxyGroups.Insert(index, group);
|
|
||||||
}
|
}
|
||||||
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
||||||
|
|
||||||
//RefreshProxyDetails(true);
|
|
||||||
//GetClashProxies(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProxiesDelayTest(bool blAll)
|
private void ProxiesDelayTest(bool blAll)
|
||||||
|
|
|
@ -381,7 +381,7 @@ namespace v2rayN.ViewModels
|
||||||
StatisticsHandler.Instance.Init(_config, UpdateStatisticsHandler);
|
StatisticsHandler.Instance.Init(_config, UpdateStatisticsHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegUpdateTask(_config, UpdateTaskHandler);
|
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);
|
||||||
RefreshRoutingsMenu();
|
RefreshRoutingsMenu();
|
||||||
//RefreshServers();
|
//RefreshServers();
|
||||||
|
|
||||||
|
@ -1015,73 +1015,5 @@ namespace v2rayN.ViewModels
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion UI
|
#endregion UI
|
||||||
|
|
||||||
#region UpdateTask
|
|
||||||
|
|
||||||
private void RegUpdateTask(Config config, Action<bool, string> update)
|
|
||||||
{
|
|
||||||
Task.Run(() => UpdateTaskRunSubscription(config, update));
|
|
||||||
Task.Run(() => UpdateTaskRunGeo(config, update));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UpdateTaskRunSubscription(Config config, Action<bool, string> update)
|
|
||||||
{
|
|
||||||
await Task.Delay(60000);
|
|
||||||
Logging.SaveLog("UpdateTaskRunSubscription");
|
|
||||||
|
|
||||||
var updateHandle = new UpdateHandler();
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
var updateTime = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds();
|
|
||||||
var lstSubs = LazyConfig.Instance.SubItems()
|
|
||||||
.Where(t => t.autoUpdateInterval > 0)
|
|
||||||
.Where(t => updateTime - t.updateTime >= t.autoUpdateInterval * 60)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (var item in lstSubs)
|
|
||||||
{
|
|
||||||
updateHandle.UpdateSubscriptionProcess(config, item.id, true, (bool success, string msg) =>
|
|
||||||
{
|
|
||||||
update(success, msg);
|
|
||||||
if (success)
|
|
||||||
Logging.SaveLog("subscription" + msg);
|
|
||||||
});
|
|
||||||
item.updateTime = updateTime;
|
|
||||||
ConfigHandler.AddSubItem(config, item);
|
|
||||||
|
|
||||||
await Task.Delay(5000);
|
|
||||||
}
|
|
||||||
await Task.Delay(60000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UpdateTaskRunGeo(Config config, Action<bool, string> update)
|
|
||||||
{
|
|
||||||
var autoUpdateGeoTime = DateTime.Now;
|
|
||||||
|
|
||||||
await Task.Delay(1000 * 120);
|
|
||||||
Logging.SaveLog("UpdateTaskRunGeo");
|
|
||||||
|
|
||||||
var updateHandle = new UpdateHandler();
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
var dtNow = DateTime.Now;
|
|
||||||
if (config.guiItem.autoUpdateInterval > 0)
|
|
||||||
{
|
|
||||||
if ((dtNow - autoUpdateGeoTime).Hours % config.guiItem.autoUpdateInterval == 0)
|
|
||||||
{
|
|
||||||
updateHandle.UpdateGeoFileAll(config, (bool success, string msg) =>
|
|
||||||
{
|
|
||||||
update(false, msg);
|
|
||||||
});
|
|
||||||
autoUpdateGeoTime = dtNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(1000 * 3600);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion UpdateTask
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,8 +9,8 @@ using System.Text;
|
||||||
using v2rayN.Base;
|
using v2rayN.Base;
|
||||||
using v2rayN.Enums;
|
using v2rayN.Enums;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
|
using v2rayN.Handler.CoreConfig;
|
||||||
using v2rayN.Handler.Fmt;
|
using v2rayN.Handler.Fmt;
|
||||||
using v2rayN.Handler.Statistics;
|
|
||||||
using v2rayN.Models;
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ namespace v2rayN.ViewModels
|
||||||
//servers delete
|
//servers delete
|
||||||
EditServerCmd = ReactiveCommand.Create(() =>
|
EditServerCmd = ReactiveCommand.Create(() =>
|
||||||
{
|
{
|
||||||
EditServer(false, EConfigType.Custom);
|
EditServer(EConfigType.Custom);
|
||||||
}, canEditRemove);
|
}, canEditRemove);
|
||||||
RemoveServerCmd = ReactiveCommand.Create(() =>
|
RemoveServerCmd = ReactiveCommand.Create(() =>
|
||||||
{
|
{
|
||||||
|
@ -346,39 +346,7 @@ namespace v2rayN.ViewModels
|
||||||
|
|
||||||
public void RefreshServersBiz()
|
public void RefreshServersBiz()
|
||||||
{
|
{
|
||||||
var lstModel = LazyConfig.Instance.ProfileItems(_config.subIndexId, _serverFilter);
|
var lstModel = LazyConfig.Instance.ProfileItemsEx(_config.subIndexId, _serverFilter);
|
||||||
|
|
||||||
ConfigHandler.SetDefaultServer(_config, lstModel);
|
|
||||||
|
|
||||||
var lstServerStat = (_config.guiItem.enableStatistics ? StatisticsHandler.Instance.ServerStat : null) ?? [];
|
|
||||||
var lstProfileExs = ProfileExHandler.Instance.ProfileExs;
|
|
||||||
lstModel = (from t in lstModel
|
|
||||||
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,
|
|
||||||
configType = t.configType,
|
|
||||||
remarks = t.remarks,
|
|
||||||
address = t.address,
|
|
||||||
port = t.port,
|
|
||||||
security = t.security,
|
|
||||||
network = t.network,
|
|
||||||
streamSecurity = t.streamSecurity,
|
|
||||||
subid = t.subid,
|
|
||||||
subRemarks = t.subRemarks,
|
|
||||||
isActive = t.indexId == _config.indexId,
|
|
||||||
sort = t33 == null ? 0 : t33.sort,
|
|
||||||
delay = t33 == null ? 0 : t33.delay,
|
|
||||||
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)
|
|
||||||
}).OrderBy(t => t.sort).ToList();
|
|
||||||
_lstProfile = JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstModel)) ?? [];
|
_lstProfile = JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstModel)) ?? [];
|
||||||
|
|
||||||
_profileItems.Clear();
|
_profileItems.Clear();
|
||||||
|
@ -448,32 +416,20 @@ namespace v2rayN.ViewModels
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EditServer(bool blNew, EConfigType eConfigType)
|
public void EditServer(EConfigType eConfigType)
|
||||||
{
|
{
|
||||||
ProfileItem item;
|
if (Utils.IsNullOrEmpty(SelectedProfile?.indexId))
|
||||||
if (blNew)
|
|
||||||
{
|
{
|
||||||
item = new()
|
return;
|
||||||
{
|
|
||||||
subid = _config.subIndexId,
|
|
||||||
configType = eConfigType,
|
|
||||||
isSub = false,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
var item = LazyConfig.Instance.GetProfileItem(SelectedProfile.indexId);
|
||||||
|
if (item is null)
|
||||||
{
|
{
|
||||||
if (Utils.IsNullOrEmpty(SelectedProfile?.indexId))
|
_noticeHandler?.Enqueue(ResUI.PleaseSelectServer);
|
||||||
{
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
item = LazyConfig.Instance.GetProfileItem(SelectedProfile.indexId);
|
|
||||||
if (item is null)
|
|
||||||
{
|
|
||||||
_noticeHandler?.Enqueue(ResUI.PleaseSelectServer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
eConfigType = item.configType;
|
|
||||||
}
|
}
|
||||||
|
eConfigType = item.configType;
|
||||||
|
|
||||||
bool? ret = false;
|
bool? ret = false;
|
||||||
if (eConfigType == EConfigType.Custom)
|
if (eConfigType == EConfigType.Custom)
|
||||||
{
|
{
|
||||||
|
@ -722,7 +678,25 @@ namespace v2rayN.ViewModels
|
||||||
_noticeHandler?.Enqueue(ResUI.PleaseSelectServer);
|
_noticeHandler?.Enqueue(ResUI.PleaseSelectServer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MainFormHandler.Instance.Export2ClientConfig(item, _config);
|
|
||||||
|
_updateView?.Invoke(EViewAction.SaveFileDialog, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Export2ClientConfigResult(string fileName, ProfileItem item)
|
||||||
|
{
|
||||||
|
if (Utils.IsNullOrEmpty(fileName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (CoreConfigHandler.GenerateClientConfig(item, fileName, out string msg, out string content) != 0)
|
||||||
|
{
|
||||||
|
Locator.Current.GetService<NoticeHandler>()?.Enqueue(msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg = string.Format(ResUI.SaveClientConfigurationIn, fileName);
|
||||||
|
Locator.Current.GetService<NoticeHandler>()?.SendMessageAndEnqueue(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Export2ShareUrl()
|
public void Export2ShareUrl()
|
||||||
|
|
|
@ -47,27 +47,7 @@ namespace v2rayN.ViewModels
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = LazyConfig.Instance.GetSubItem(SelectedSource.id);
|
if (ConfigHandler.AddSubItem(_config, SelectedSource) == 0)
|
||||||
if (item is null)
|
|
||||||
{
|
|
||||||
item = SelectedSource;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item.remarks = SelectedSource.remarks;
|
|
||||||
item.url = SelectedSource.url;
|
|
||||||
item.moreUrl = SelectedSource.moreUrl;
|
|
||||||
item.enabled = SelectedSource.enabled;
|
|
||||||
item.autoUpdateInterval = SelectedSource.autoUpdateInterval;
|
|
||||||
item.userAgent = SelectedSource.userAgent;
|
|
||||||
item.sort = SelectedSource.sort;
|
|
||||||
item.filter = SelectedSource.filter;
|
|
||||||
item.convertTarget = SelectedSource.convertTarget;
|
|
||||||
item.prevProfile = SelectedSource.prevProfile;
|
|
||||||
item.nextProfile = SelectedSource.nextProfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ConfigHandler.AddSubItem(_config, item) == 0)
|
|
||||||
{
|
{
|
||||||
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
||||||
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||||
|
|
|
@ -7,9 +7,12 @@ using ReactiveUI;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Interop;
|
||||||
using v2rayN.Base;
|
using v2rayN.Base;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
|
using v2rayN.Models;
|
||||||
using v2rayN.Resx;
|
using v2rayN.Resx;
|
||||||
|
|
||||||
namespace v2rayN.ViewModels
|
namespace v2rayN.ViewModels
|
||||||
|
@ -40,7 +43,7 @@ namespace v2rayN.ViewModels
|
||||||
{
|
{
|
||||||
_config = LazyConfig.Instance.Config;
|
_config = LazyConfig.Instance.Config;
|
||||||
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
|
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
|
||||||
MainFormHandler.Instance.RegisterSystemColorSet(_config, Application.Current.MainWindow, (bool bl) => { ModifyTheme(bl); });
|
RegisterSystemColorSet(_config, Application.Current.MainWindow, (bool bl) => { ModifyTheme(bl); });
|
||||||
|
|
||||||
BindingUI();
|
BindingUI();
|
||||||
RestoreUI();
|
RestoreUI();
|
||||||
|
@ -186,5 +189,27 @@ namespace v2rayN.ViewModels
|
||||||
|
|
||||||
_paletteHelper.SetTheme(theme);
|
_paletteHelper.SetTheme(theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RegisterSystemColorSet(Config config, Window window, Action<bool> update)
|
||||||
|
{
|
||||||
|
var helper = new WindowInteropHelper(window);
|
||||||
|
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
|
||||||
|
hwndSource.AddHook((IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) =>
|
||||||
|
{
|
||||||
|
if (config.uiItem.followSystemTheme)
|
||||||
|
{
|
||||||
|
const int WM_SETTINGCHANGE = 0x001A;
|
||||||
|
if (msg == WM_SETTINGCHANGE)
|
||||||
|
{
|
||||||
|
if (wParam == IntPtr.Zero && Marshal.PtrToStringUni(lParam) == "ImmersiveColorSet")
|
||||||
|
{
|
||||||
|
update(!WindowsUtils.IsLightTheme());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntPtr.Zero;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -37,7 +37,7 @@ namespace v2rayN.Views
|
||||||
ViewModel = new MainWindowViewModel(UpdateViewHandler);
|
ViewModel = new MainWindowViewModel(UpdateViewHandler);
|
||||||
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
|
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
|
||||||
|
|
||||||
MainFormHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null);
|
WindowsHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null);
|
||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
|
@ -252,8 +252,8 @@ namespace v2rayN.Views
|
||||||
case EViewAction.DispatcherRefreshIcon:
|
case EViewAction.DispatcherRefreshIcon:
|
||||||
Application.Current?.Dispatcher.Invoke((() =>
|
Application.Current?.Dispatcher.Invoke((() =>
|
||||||
{
|
{
|
||||||
tbNotify.Icon = MainFormHandler.Instance.GetNotifyIcon(_config);
|
tbNotify.Icon = WindowsHandler.Instance.GetNotifyIcon(_config);
|
||||||
this.Icon = MainFormHandler.Instance.GetAppIcon(_config);
|
this.Icon = WindowsHandler.Instance.GetAppIcon(_config);
|
||||||
}), DispatcherPriority.Normal);
|
}), DispatcherPriority.Normal);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using MaterialDesignThemes.Wpf;
|
using MaterialDesignThemes.Wpf;
|
||||||
|
using Microsoft.Win32;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using Splat;
|
using Splat;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
@ -122,6 +123,21 @@ namespace v2rayN.Views
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EViewAction.SaveFileDialog:
|
||||||
|
if (obj is null) return false;
|
||||||
|
SaveFileDialog fileDialog = new()
|
||||||
|
{
|
||||||
|
Filter = "Config|*.json",
|
||||||
|
FilterIndex = 2,
|
||||||
|
RestoreDirectory = true
|
||||||
|
};
|
||||||
|
if (fileDialog.ShowDialog() != true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ViewModel?.Export2ClientConfigResult(fileDialog.FileName, (ProfileItem)obj);
|
||||||
|
break;
|
||||||
|
|
||||||
case EViewAction.AddServerWindow:
|
case EViewAction.AddServerWindow:
|
||||||
if (obj is null) return false;
|
if (obj is null) return false;
|
||||||
return (new AddServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
|
return (new AddServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
|
||||||
|
@ -188,7 +204,7 @@ namespace v2rayN.Views
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ViewModel?.EditServer(false, EConfigType.Custom);
|
ViewModel?.EditServer(EConfigType.Custom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +240,7 @@ namespace v2rayN.Views
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key.D:
|
case Key.D:
|
||||||
ViewModel?.EditServer(false, EConfigType.Custom);
|
ViewModel?.EditServer(EConfigType.Custom);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key.F:
|
case Key.F:
|
||||||
|
|
Loading…
Reference in New Issue