mirror of https://github.com/2dust/v2rayN
Refactor code to decouple view and viewmodel
parent
a9860418ba
commit
7faabdc375
|
@ -4,6 +4,7 @@
|
|||
{
|
||||
CloseWindow,
|
||||
ShowYesNo,
|
||||
SaveFileDialog,
|
||||
AddBatchRoutingRulesYesNo,
|
||||
AdjustMainLvColWidth,
|
||||
ProfilesFocus,
|
||||
|
|
|
@ -355,13 +355,64 @@ namespace v2rayN.Handler
|
|||
|
||||
#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>
|
||||
/// Add or edit server
|
||||
/// </summary>
|
||||
/// <param name="config"></param>
|
||||
/// <param name="profileItem"></param>
|
||||
/// <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;
|
||||
|
||||
|
@ -619,7 +670,21 @@ namespace v2rayN.Handler
|
|||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
@ -1189,7 +1254,7 @@ namespace v2rayN.Handler
|
|||
|
||||
var addStatus = profileItem.configType switch
|
||||
{
|
||||
EConfigType.VMess => AddServer(config, profileItem, false),
|
||||
EConfigType.VMess => AddVMessServer(config, profileItem, false),
|
||||
EConfigType.Shadowsocks => AddShadowsocksServer(config, profileItem, false),
|
||||
EConfigType.Socks => AddSocksServer(config, profileItem, false),
|
||||
EConfigType.Trojan => AddTrojanServer(config, profileItem, false),
|
||||
|
@ -1419,21 +1484,41 @@ namespace v2rayN.Handler
|
|||
|
||||
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;
|
||||
if (SQLiteHelper.Instance.Table<SubItem>().Count() > 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using v2rayN.Enums;
|
||||
using v2rayN.Handler.Statistics;
|
||||
using v2rayN.Models;
|
||||
|
||||
namespace v2rayN.Handler
|
||||
|
@ -119,6 +120,45 @@ namespace v2rayN.Handler
|
|||
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)
|
||||
{
|
||||
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 Splat;
|
||||
using System.Drawing;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Imaging;
|
||||
using v2rayN.Enums;
|
||||
using v2rayN.Handler.CoreConfig;
|
||||
using v2rayN.Models;
|
||||
using v2rayN.Resx;
|
||||
|
||||
namespace v2rayN.Handler
|
||||
{
|
||||
public sealed class MainFormHandler
|
||||
public sealed class WindowsHandler
|
||||
{
|
||||
private static readonly Lazy<MainFormHandler> instance = new(() => new());
|
||||
public static MainFormHandler Instance => instance.Value;
|
||||
private static readonly Lazy<WindowsHandler> instance = new(() => new());
|
||||
public static WindowsHandler Instance => instance.Value;
|
||||
|
||||
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)
|
||||
{
|
||||
HotkeyHandler.Instance.UpdateViewEvent += update;
|
||||
HotkeyHandler.Instance.HotkeyTriggerEvent += handler;
|
||||
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;
|
||||
}
|
||||
|
||||
var item = LazyConfig.Instance.GetProfileItem(SelectedSource.indexId);
|
||||
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)
|
||||
if (ConfigHandler.EditCustomServer(_config, SelectedSource) == 0)
|
||||
{
|
||||
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
||||
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
|
|
|
@ -85,54 +85,7 @@ namespace v2rayN.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
var item = LazyConfig.Instance.GetProfileItem(SelectedSource.indexId);
|
||||
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)
|
||||
if (ConfigHandler.AddServer(_config, SelectedSource) == 0)
|
||||
{
|
||||
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
||||
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
|
|
|
@ -162,8 +162,10 @@ namespace v2rayN.ViewModels
|
|||
|
||||
if (mode != ERuleMode.Unchanged)
|
||||
{
|
||||
Dictionary<string, string> headers = new Dictionary<string, string>();
|
||||
headers.Add("mode", mode.ToString().ToLower());
|
||||
Dictionary<string, string> headers = new()
|
||||
{
|
||||
{ "mode", mode.ToString().ToLower() }
|
||||
};
|
||||
ClashApiHandler.Instance.ClashConfigUpdate(headers);
|
||||
}
|
||||
}
|
||||
|
@ -382,15 +384,10 @@ namespace v2rayN.ViewModels
|
|||
_proxyGroups.Replace(group, group2);
|
||||
|
||||
SelectedGroup = group2;
|
||||
|
||||
//var index = _proxyGroups.IndexOf(group);
|
||||
//_proxyGroups.Remove(group);
|
||||
//_proxyGroups.Insert(index, group);
|
||||
|
||||
}
|
||||
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
||||
|
||||
//RefreshProxyDetails(true);
|
||||
//GetClashProxies(true);
|
||||
|
||||
}
|
||||
|
||||
private void ProxiesDelayTest(bool blAll)
|
||||
|
|
|
@ -381,7 +381,7 @@ namespace v2rayN.ViewModels
|
|||
StatisticsHandler.Instance.Init(_config, UpdateStatisticsHandler);
|
||||
}
|
||||
|
||||
RegUpdateTask(_config, UpdateTaskHandler);
|
||||
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);
|
||||
RefreshRoutingsMenu();
|
||||
//RefreshServers();
|
||||
|
||||
|
@ -1015,73 +1015,5 @@ namespace v2rayN.ViewModels
|
|||
}
|
||||
|
||||
#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.Enums;
|
||||
using v2rayN.Handler;
|
||||
using v2rayN.Handler.CoreConfig;
|
||||
using v2rayN.Handler.Fmt;
|
||||
using v2rayN.Handler.Statistics;
|
||||
using v2rayN.Models;
|
||||
using v2rayN.Resx;
|
||||
|
||||
|
@ -143,7 +143,7 @@ namespace v2rayN.ViewModels
|
|||
//servers delete
|
||||
EditServerCmd = ReactiveCommand.Create(() =>
|
||||
{
|
||||
EditServer(false, EConfigType.Custom);
|
||||
EditServer(EConfigType.Custom);
|
||||
}, canEditRemove);
|
||||
RemoveServerCmd = ReactiveCommand.Create(() =>
|
||||
{
|
||||
|
@ -346,39 +346,7 @@ namespace v2rayN.ViewModels
|
|||
|
||||
public void RefreshServersBiz()
|
||||
{
|
||||
var lstModel = LazyConfig.Instance.ProfileItems(_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();
|
||||
var lstModel = LazyConfig.Instance.ProfileItemsEx(_config.subIndexId, _serverFilter);
|
||||
_lstProfile = JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstModel)) ?? [];
|
||||
|
||||
_profileItems.Clear();
|
||||
|
@ -448,32 +416,20 @@ namespace v2rayN.ViewModels
|
|||
return 0;
|
||||
}
|
||||
|
||||
public void EditServer(bool blNew, EConfigType eConfigType)
|
||||
public void EditServer(EConfigType eConfigType)
|
||||
{
|
||||
ProfileItem item;
|
||||
if (blNew)
|
||||
if (Utils.IsNullOrEmpty(SelectedProfile?.indexId))
|
||||
{
|
||||
item = new()
|
||||
{
|
||||
subid = _config.subIndexId,
|
||||
configType = eConfigType,
|
||||
isSub = false,
|
||||
};
|
||||
return;
|
||||
}
|
||||
else
|
||||
var item = LazyConfig.Instance.GetProfileItem(SelectedProfile.indexId);
|
||||
if (item is null)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(SelectedProfile?.indexId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
item = LazyConfig.Instance.GetProfileItem(SelectedProfile.indexId);
|
||||
if (item is null)
|
||||
{
|
||||
_noticeHandler?.Enqueue(ResUI.PleaseSelectServer);
|
||||
return;
|
||||
}
|
||||
eConfigType = item.configType;
|
||||
_noticeHandler?.Enqueue(ResUI.PleaseSelectServer);
|
||||
return;
|
||||
}
|
||||
eConfigType = item.configType;
|
||||
|
||||
bool? ret = false;
|
||||
if (eConfigType == EConfigType.Custom)
|
||||
{
|
||||
|
@ -722,7 +678,25 @@ namespace v2rayN.ViewModels
|
|||
_noticeHandler?.Enqueue(ResUI.PleaseSelectServer);
|
||||
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()
|
||||
|
|
|
@ -47,27 +47,7 @@ namespace v2rayN.ViewModels
|
|||
return;
|
||||
}
|
||||
|
||||
var item = LazyConfig.Instance.GetSubItem(SelectedSource.id);
|
||||
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)
|
||||
if (ConfigHandler.AddSubItem(_config, SelectedSource) == 0)
|
||||
{
|
||||
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
|
||||
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
|
|
|
@ -7,9 +7,12 @@ using ReactiveUI;
|
|||
using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
using System.Reactive.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using v2rayN.Base;
|
||||
using v2rayN.Handler;
|
||||
using v2rayN.Models;
|
||||
using v2rayN.Resx;
|
||||
|
||||
namespace v2rayN.ViewModels
|
||||
|
@ -40,7 +43,7 @@ namespace v2rayN.ViewModels
|
|||
{
|
||||
_config = LazyConfig.Instance.Config;
|
||||
_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();
|
||||
RestoreUI();
|
||||
|
@ -186,5 +189,27 @@ namespace v2rayN.ViewModels
|
|||
|
||||
_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);
|
||||
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
|
||||
|
||||
MainFormHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null);
|
||||
WindowsHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null);
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
|
@ -252,8 +252,8 @@ namespace v2rayN.Views
|
|||
case EViewAction.DispatcherRefreshIcon:
|
||||
Application.Current?.Dispatcher.Invoke((() =>
|
||||
{
|
||||
tbNotify.Icon = MainFormHandler.Instance.GetNotifyIcon(_config);
|
||||
this.Icon = MainFormHandler.Instance.GetAppIcon(_config);
|
||||
tbNotify.Icon = WindowsHandler.Instance.GetNotifyIcon(_config);
|
||||
this.Icon = WindowsHandler.Instance.GetAppIcon(_config);
|
||||
}), DispatcherPriority.Normal);
|
||||
break;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MaterialDesignThemes.Wpf;
|
||||
using Microsoft.Win32;
|
||||
using ReactiveUI;
|
||||
using Splat;
|
||||
using System.Reactive.Disposables;
|
||||
|
@ -122,6 +123,21 @@ namespace v2rayN.Views
|
|||
}
|
||||
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:
|
||||
if (obj is null) return false;
|
||||
return (new AddServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
|
||||
|
@ -188,7 +204,7 @@ namespace v2rayN.Views
|
|||
}
|
||||
else
|
||||
{
|
||||
ViewModel?.EditServer(false, EConfigType.Custom);
|
||||
ViewModel?.EditServer(EConfigType.Custom);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,7 +240,7 @@ namespace v2rayN.Views
|
|||
break;
|
||||
|
||||
case Key.D:
|
||||
ViewModel?.EditServer(false, EConfigType.Custom);
|
||||
ViewModel?.EditServer(EConfigType.Custom);
|
||||
break;
|
||||
|
||||
case Key.F:
|
||||
|
|
Loading…
Reference in New Issue