diff --git a/v2rayN/v2rayN/Enums/EViewAction.cs b/v2rayN/v2rayN/Enums/EViewAction.cs
index 19156be2..b90682a1 100644
--- a/v2rayN/v2rayN/Enums/EViewAction.cs
+++ b/v2rayN/v2rayN/Enums/EViewAction.cs
@@ -4,6 +4,7 @@
{
CloseWindow,
ShowYesNo,
+ SaveFileDialog,
AddBatchRoutingRulesYesNo,
AdjustMainLvColWidth,
ProfilesFocus,
diff --git a/v2rayN/v2rayN/Handler/ConfigHandler.cs b/v2rayN/v2rayN/Handler/ConfigHandler.cs
index 09c45c32..8e8c0853 100644
--- a/v2rayN/v2rayN/Handler/ConfigHandler.cs
+++ b/v2rayN/v2rayN/Handler/ConfigHandler.cs
@@ -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;
+ }
+
///
/// Add or edit server
///
///
///
///
- 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
///
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().Count() > 0)
{
maxSort = SQLiteHelper.Instance.Table().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;
}
diff --git a/v2rayN/v2rayN/Handler/LazyConfig.cs b/v2rayN/v2rayN/Handler/LazyConfig.cs
index 62f45298..3017466f 100644
--- a/v2rayN/v2rayN/Handler/LazyConfig.cs
+++ b/v2rayN/v2rayN/Handler/LazyConfig.cs
@@ -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(sql).ToList();
}
+ public List 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))
diff --git a/v2rayN/v2rayN/Handler/TaskHandler.cs b/v2rayN/v2rayN/Handler/TaskHandler.cs
new file mode 100644
index 00000000..e7657ccd
--- /dev/null
+++ b/v2rayN/v2rayN/Handler/TaskHandler.cs
@@ -0,0 +1,78 @@
+using v2rayN.Models;
+
+namespace v2rayN.Handler
+{
+ internal class TaskHandler
+ {
+ private static readonly Lazy _instance = new(() => new());
+ public static TaskHandler Instance => _instance.Value;
+
+ public TaskHandler()
+ {
+ }
+
+ public void RegUpdateTask(Config config, Action update)
+ {
+ Task.Run(() => UpdateTaskRunSubscription(config, update));
+ Task.Run(() => UpdateTaskRunGeo(config, update));
+ }
+
+ private async Task UpdateTaskRunSubscription(Config config, Action 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 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);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Handler/MainFormHandler.cs b/v2rayN/v2rayN/Handler/WindowsHandler.cs
similarity index 64%
rename from v2rayN/v2rayN/Handler/MainFormHandler.cs
rename to v2rayN/v2rayN/Handler/WindowsHandler.cs
index 8547277b..4b6f62ba 100644
--- a/v2rayN/v2rayN/Handler/MainFormHandler.cs
+++ b/v2rayN/v2rayN/Handler/WindowsHandler.cs
@@ -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 instance = new(() => new());
- public static MainFormHandler Instance => instance.Value;
+ private static readonly Lazy 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()?.Enqueue(msg);
- }
- else
- {
- msg = string.Format(ResUI.SaveClientConfigurationIn, fileName);
- Locator.Current.GetService()?.SendMessageAndEnqueue(msg);
- }
- }
-
public void RegisterGlobalHotkey(Config config, Action handler, Action? update)
{
HotkeyHandler.Instance.UpdateViewEvent += update;
HotkeyHandler.Instance.HotkeyTriggerEvent += handler;
HotkeyHandler.Instance.Load();
}
-
- public void RegisterSystemColorSet(Config config, Window window, Action 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;
- });
- }
}
}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/ViewModels/AddServer2ViewModel.cs b/v2rayN/v2rayN/ViewModels/AddServer2ViewModel.cs
index aa70027e..4cc62f35 100644
--- a/v2rayN/v2rayN/ViewModels/AddServer2ViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/AddServer2ViewModel.cs
@@ -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);
diff --git a/v2rayN/v2rayN/ViewModels/AddServerViewModel.cs b/v2rayN/v2rayN/ViewModels/AddServerViewModel.cs
index bb9f4f0e..12c86f9c 100644
--- a/v2rayN/v2rayN/ViewModels/AddServerViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/AddServerViewModel.cs
@@ -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);
diff --git a/v2rayN/v2rayN/ViewModels/ClashProxiesViewModel.cs b/v2rayN/v2rayN/ViewModels/ClashProxiesViewModel.cs
index 7bb2d92c..48b4e91b 100644
--- a/v2rayN/v2rayN/ViewModels/ClashProxiesViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/ClashProxiesViewModel.cs
@@ -162,8 +162,10 @@ namespace v2rayN.ViewModels
if (mode != ERuleMode.Unchanged)
{
- Dictionary headers = new Dictionary();
- headers.Add("mode", mode.ToString().ToLower());
+ Dictionary 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)
diff --git a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs
index 22cd0d44..7afacf58 100644
--- a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs
@@ -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 update)
- {
- Task.Run(() => UpdateTaskRunSubscription(config, update));
- Task.Run(() => UpdateTaskRunGeo(config, update));
- }
-
- private async Task UpdateTaskRunSubscription(Config config, Action 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 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
}
}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/ViewModels/ProfilesViewModel.cs b/v2rayN/v2rayN/ViewModels/ProfilesViewModel.cs
index 6cc41d1e..2eeb7f95 100644
--- a/v2rayN/v2rayN/ViewModels/ProfilesViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/ProfilesViewModel.cs
@@ -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>(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()?.Enqueue(msg);
+ }
+ else
+ {
+ msg = string.Format(ResUI.SaveClientConfigurationIn, fileName);
+ Locator.Current.GetService()?.SendMessageAndEnqueue(msg);
+ }
}
public void Export2ShareUrl()
diff --git a/v2rayN/v2rayN/ViewModels/SubEditViewModel.cs b/v2rayN/v2rayN/ViewModels/SubEditViewModel.cs
index 1f6dec86..8d243480 100644
--- a/v2rayN/v2rayN/ViewModels/SubEditViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/SubEditViewModel.cs
@@ -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);
diff --git a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs
index ffb8cebe..cc43c4e9 100644
--- a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs
@@ -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();
- 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 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;
+ });
+ }
}
}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml.cs b/v2rayN/v2rayN/Views/MainWindow.xaml.cs
index 34082e9f..8f65ef90 100644
--- a/v2rayN/v2rayN/Views/MainWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/MainWindow.xaml.cs
@@ -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;
diff --git a/v2rayN/v2rayN/Views/ProfilesView.xaml.cs b/v2rayN/v2rayN/Views/ProfilesView.xaml.cs
index bff475ec..96a53920 100644
--- a/v2rayN/v2rayN/Views/ProfilesView.xaml.cs
+++ b/v2rayN/v2rayN/Views/ProfilesView.xaml.cs
@@ -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: