diff --git a/v2rayN/v2rayN/Common/ProxySetting.cs b/v2rayN/v2rayN/Common/ProxySetting.cs index cab0763317..1b102f5c6a 100644 --- a/v2rayN/v2rayN/Common/ProxySetting.cs +++ b/v2rayN/v2rayN/Common/ProxySetting.cs @@ -11,24 +11,24 @@ private static bool SetProxyFallback(string? strProxy, string? exceptions, int t { if (type == 1) { - Utils.RegWriteValue(_regPath, "ProxyEnable", 0); - Utils.RegWriteValue(_regPath, "ProxyServer", string.Empty); - Utils.RegWriteValue(_regPath, "ProxyOverride", string.Empty); - Utils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty); + WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 0); + WindowsUtils.RegWriteValue(_regPath, "ProxyServer", string.Empty); + WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", string.Empty); + WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty); } if (type == 2) { - Utils.RegWriteValue(_regPath, "ProxyEnable", 1); - Utils.RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty); - Utils.RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty); - Utils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty); + WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 1); + WindowsUtils.RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty); + WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty); + WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty); } else if (type == 4) { - Utils.RegWriteValue(_regPath, "ProxyEnable", 0); - Utils.RegWriteValue(_regPath, "ProxyServer", string.Empty); - Utils.RegWriteValue(_regPath, "ProxyOverride", string.Empty); - Utils.RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty); + WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 0); + WindowsUtils.RegWriteValue(_regPath, "ProxyServer", string.Empty); + WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", string.Empty); + WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty); } return true; } diff --git a/v2rayN/v2rayN/Common/Utils.cs b/v2rayN/v2rayN/Common/Utils.cs index 39f2f9a84b..77169165c8 100644 --- a/v2rayN/v2rayN/Common/Utils.cs +++ b/v2rayN/v2rayN/Common/Utils.cs @@ -1,23 +1,15 @@ -using Microsoft.Win32; -using Microsoft.Win32.TaskScheduler; -using System.Collections.Specialized; +using System.Collections.Specialized; using System.Diagnostics; -using System.Drawing; using System.IO; using System.IO.Compression; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; -using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Principal; using System.Text; using System.Text.RegularExpressions; -using System.Windows; -using System.Windows.Interop; -using System.Windows.Media; -using System.Windows.Media.Imaging; namespace v2rayN { @@ -345,14 +337,6 @@ public static string GetMD5(string str) return sb.ToString(); } - public static ImageSource IconToImageSource(Icon icon) - { - return Imaging.CreateBitmapSourceFromHIcon( - icon.Handle, - new System.Windows.Int32Rect(0, 0, icon.Width, icon.Height), - BitmapSizeOptions.FromEmptyOptions()); - } - /// /// idn to idc /// @@ -420,11 +404,7 @@ public static bool IsNumeric(string oText) } } - /// - /// 文本 - /// - /// - /// + public static bool IsNullOrEmpty(string? text) { if (string.IsNullOrWhiteSpace(text)) @@ -631,43 +611,6 @@ public static string GetVersion(bool blFull = true) } } - /// - /// 获取剪贴板数 - /// - /// - public static string? GetClipboardData() - { - string? strData = string.Empty; - try - { - IDataObject data = Clipboard.GetDataObject(); - if (data.GetDataPresent(DataFormats.UnicodeText)) - { - strData = data.GetData(DataFormats.UnicodeText)?.ToString(); - } - return strData; - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return strData; - } - - /// - /// 拷贝至剪贴板 - /// - /// - public static void SetClipboardData(string strData) - { - try - { - Clipboard.SetText(strData); - } - catch - { - } - } /// /// 取得GUID @@ -752,23 +695,6 @@ public static void ProcessStart(string fileName, string arguments = "") } } - public static void SetDarkBorder(System.Windows.Window window, bool dark) - { - // Make sure the handle is created before the window is shown - IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(window).EnsureHandle(); - int attribute = dark ? 1 : 0; - uint attributeSize = (uint)Marshal.SizeOf(attribute); - DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, ref attribute, attributeSize); - DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize); - } - - public static bool IsLightTheme() - { - using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"); - var value = key?.GetValue("AppsUseLightTheme"); - return value is int i && i > 0; - } - /// /// 获取系统hosts /// @@ -958,12 +884,13 @@ public static void SetAutoRun(string AutoRunRegPath, string AutoRunName, bool ru try { var autoRunName = $"{AutoRunName}_{GetMD5(StartupPath())}"; + WindowsUtils. - //delete first - RegWriteValue(AutoRunRegPath, autoRunName, ""); + //delete first + RegWriteValue(AutoRunRegPath, autoRunName, ""); if (IsAdministrator()) { - AutoStart(autoRunName, "", ""); + WindowsUtils.AutoStart(autoRunName, "", ""); } if (run) @@ -971,11 +898,11 @@ public static void SetAutoRun(string AutoRunRegPath, string AutoRunName, bool ru string exePath = GetExePath(); if (IsAdministrator()) { - AutoStart(autoRunName, exePath, ""); + WindowsUtils.AutoStart(autoRunName, exePath, ""); } else { - RegWriteValue(AutoRunRegPath, autoRunName, exePath.AppendQuotes()); + WindowsUtils.RegWriteValue(AutoRunRegPath, autoRunName, exePath.AppendQuotes()); } } } @@ -985,146 +912,8 @@ public static void SetAutoRun(string AutoRunRegPath, string AutoRunName, bool ru } } - public static string? RegReadValue(string path, string name, string def) - { - RegistryKey? regKey = null; - try - { - regKey = Registry.CurrentUser.OpenSubKey(path, false); - string? value = regKey?.GetValue(name) as string; - if (IsNullOrEmpty(value)) - { - return def; - } - else - { - return value; - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - finally - { - regKey?.Close(); - } - return def; - } - - public static void RegWriteValue(string path, string name, object value) - { - RegistryKey? regKey = null; - try - { - regKey = Registry.CurrentUser.CreateSubKey(path); - if (IsNullOrEmpty(value.ToString())) - { - regKey?.DeleteValue(name, false); - } - else - { - regKey?.SetValue(name, value); - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - finally - { - regKey?.Close(); - } - } - - /// - /// Auto Start via TaskService - /// - /// - /// - /// - /// - public static void AutoStart(string taskName, string fileName, string description) - { - if (Utils.IsNullOrEmpty(taskName)) - { - return; - } - string TaskName = taskName; - var logonUser = WindowsIdentity.GetCurrent().Name; - string taskDescription = description; - string deamonFileName = fileName; - - using var taskService = new TaskService(); - var tasks = taskService.RootFolder.GetTasks(new Regex(TaskName)); - foreach (var t in tasks) - { - taskService.RootFolder.DeleteTask(t.Name); - } - if (Utils.IsNullOrEmpty(fileName)) - { - return; - } - - var task = taskService.NewTask(); - task.RegistrationInfo.Description = taskDescription; - task.Settings.DisallowStartIfOnBatteries = false; - task.Settings.StopIfGoingOnBatteries = false; - task.Settings.RunOnlyIfIdle = false; - task.Settings.IdleSettings.StopOnIdleEnd = false; - task.Settings.ExecutionTimeLimit = TimeSpan.Zero; - task.Triggers.Add(new LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(10) }); - task.Principal.RunLevel = TaskRunLevel.Highest; - task.Actions.Add(new ExecAction(deamonFileName.AppendQuotes(), null, Path.GetDirectoryName(deamonFileName))); - - taskService.RootFolder.RegisterTaskDefinition(TaskName, task); - } - - public static void RemoveTunDevice() - { - try - { - var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun")); - var guid = new Guid(sum); - string pnputilPath = @"C:\Windows\System32\pnputil.exe"; - string arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """; - - // Try to remove the device - Process proc = new() - { - StartInfo = new() - { - FileName = pnputilPath, - Arguments = arg, - RedirectStandardOutput = true, - UseShellExecute = false, - CreateNoWindow = true - } - }; - - proc.Start(); - var output = proc.StandardOutput.ReadToEnd(); - proc.WaitForExit(); - } - catch - { - } - } - #endregion 开机自动启动等 - #region Windows API - - [Flags] - public enum DWMWINDOWATTRIBUTE : uint - { - DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19, - DWMWA_USE_IMMERSIVE_DARK_MODE = 20, - } - - [DllImport("dwmapi.dll")] - public static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref int attributeValue, uint attributeSize); - #endregion Windows API } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/WindowsUtils.cs b/v2rayN/v2rayN/Common/WindowsUtils.cs new file mode 100644 index 0000000000..09f13cc1bf --- /dev/null +++ b/v2rayN/v2rayN/Common/WindowsUtils.cs @@ -0,0 +1,223 @@ +using Microsoft.Win32; +using Microsoft.Win32.TaskScheduler; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Principal; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace v2rayN +{ + internal static class WindowsUtils + { + + /// + /// 获取剪贴板数 + /// + /// + public static string? GetClipboardData() + { + string? strData = string.Empty; + try + { + IDataObject data = Clipboard.GetDataObject(); + if (data.GetDataPresent(DataFormats.UnicodeText)) + { + strData = data.GetData(DataFormats.UnicodeText)?.ToString(); + } + return strData; + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return strData; + } + + /// + /// 拷贝至剪贴板 + /// + /// + public static void SetClipboardData(string strData) + { + try + { + Clipboard.SetText(strData); + } + catch + { + } + } + /// + /// Auto Start via TaskService + /// + /// + /// + /// + /// + public static void AutoStart(string taskName, string fileName, string description) + { + if (Utils.IsNullOrEmpty(taskName)) + { + return; + } + string TaskName = taskName; + var logonUser = WindowsIdentity.GetCurrent().Name; + string taskDescription = description; + string deamonFileName = fileName; + + using var taskService = new TaskService(); + var tasks = taskService.RootFolder.GetTasks(new Regex(TaskName)); + foreach (var t in tasks) + { + taskService.RootFolder.DeleteTask(t.Name); + } + if (Utils.IsNullOrEmpty(fileName)) + { + return; + } + + var task = taskService.NewTask(); + task.RegistrationInfo.Description = taskDescription; + task.Settings.DisallowStartIfOnBatteries = false; + task.Settings.StopIfGoingOnBatteries = false; + task.Settings.RunOnlyIfIdle = false; + task.Settings.IdleSettings.StopOnIdleEnd = false; + task.Settings.ExecutionTimeLimit = TimeSpan.Zero; + task.Triggers.Add(new LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(10) }); + task.Principal.RunLevel = TaskRunLevel.Highest; + task.Actions.Add(new ExecAction(deamonFileName.AppendQuotes(), null, Path.GetDirectoryName(deamonFileName))); + + taskService.RootFolder.RegisterTaskDefinition(TaskName, task); + } + + [DllImport("dwmapi.dll")] + public static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref int attributeValue, uint attributeSize); + + public static ImageSource IconToImageSource(Icon icon) + { + return Imaging.CreateBitmapSourceFromHIcon( + icon.Handle, + new System.Windows.Int32Rect(0, 0, icon.Width, icon.Height), + BitmapSizeOptions.FromEmptyOptions()); + } + + public static bool IsLightTheme() + { + using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"); + var value = key?.GetValue("AppsUseLightTheme"); + return value is int i && i > 0; + } + + public static string? RegReadValue(string path, string name, string def) + { + RegistryKey? regKey = null; + try + { + regKey = Registry.CurrentUser.OpenSubKey(path, false); + string? value = regKey?.GetValue(name) as string; + if (Utils.IsNullOrEmpty(value)) + { + return def; + } + else + { + return value; + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + finally + { + regKey?.Close(); + } + return def; + } + + public static void RegWriteValue(string path, string name, object value) + { + RegistryKey? regKey = null; + try + { + regKey = Registry.CurrentUser.CreateSubKey(path); + if (Utils.IsNullOrEmpty(value.ToString())) + { + regKey?.DeleteValue(name, false); + } + else + { + regKey?.SetValue(name, value); + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + finally + { + regKey?.Close(); + } + } + + public static void RemoveTunDevice() + { + try + { + var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun")); + var guid = new Guid(sum); + string pnputilPath = @"C:\Windows\System32\pnputil.exe"; + string arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """; + + // Try to remove the device + Process proc = new() + { + StartInfo = new() + { + FileName = pnputilPath, + Arguments = arg, + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + + proc.Start(); + var output = proc.StandardOutput.ReadToEnd(); + proc.WaitForExit(); + } + catch + { + } + } + + public static void SetDarkBorder(System.Windows.Window window, bool dark) + { + // Make sure the handle is created before the window is shown + IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(window).EnsureHandle(); + int attribute = dark ? 1 : 0; + uint attributeSize = (uint)Marshal.SizeOf(attribute); + DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, ref attribute, attributeSize); + DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize); + } + + #region Windows API + + [Flags] + public enum DWMWINDOWATTRIBUTE : uint + { + DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19, + DWMWA_USE_IMMERSIVE_DARK_MODE = 20, + } + + #endregion Windows API + } +} \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/EViewAction.cs b/v2rayN/v2rayN/Enums/EViewAction.cs index 2db8b30f13..312e7ff779 100644 --- a/v2rayN/v2rayN/Enums/EViewAction.cs +++ b/v2rayN/v2rayN/Enums/EViewAction.cs @@ -10,6 +10,8 @@ public enum EViewAction ShareSub, ShareServer, ShowHideWindow, + ScanScreenTask, + Shutdown, SubEditWindow, RoutingRuleSettingWindow, RoutingRuleDetailsWindow, @@ -24,10 +26,10 @@ public enum EViewAction DispatcherRefreshConnections, DispatcherRefreshProxyGroups, DispatcherProxiesDelayTest, - DispatcherStatistics, DispatcherServerAvailability, DispatcherReload, DispatcherRefreshServersBiz, + DispatcherRefreshIcon, } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Handler/CoreHandler.cs b/v2rayN/v2rayN/Handler/CoreHandler.cs index f21f9dac86..37866d0f0d 100644 --- a/v2rayN/v2rayN/Handler/CoreHandler.cs +++ b/v2rayN/v2rayN/Handler/CoreHandler.cs @@ -46,11 +46,11 @@ public void LoadCore(ProfileItem? node) ShowMsg(false, msg); ShowMsg(true, $"{node.GetSummary()}"); CoreStop(); - if (_config.tunModeItem.enableTun) - { - Thread.Sleep(1000); - Utils.RemoveTunDevice(); - } + //if (_config.tunModeItem.enableTun) + //{ + // Thread.Sleep(1000); + // WindowsUtils.RemoveTunDevice(); + //} CoreStart(node); diff --git a/v2rayN/v2rayN/Handler/HotkeyHandler.cs b/v2rayN/v2rayN/Handler/HotkeyHandler.cs index 31a733c46d..d91cddeb95 100644 --- a/v2rayN/v2rayN/Handler/HotkeyHandler.cs +++ b/v2rayN/v2rayN/Handler/HotkeyHandler.cs @@ -43,7 +43,7 @@ private void Init() if (_config.globalHotkeys == null) return; foreach (var item in _config.globalHotkeys) { - if (item.KeyCode != null && item.KeyCode != Key.None) + if (item.KeyCode != null && (Key)item.KeyCode != Key.None) { int key = KeyInterop.VirtualKeyFromKey((Key)item.KeyCode); KeyModifiers modifiers = KeyModifiers.None; diff --git a/v2rayN/v2rayN/Handler/MainFormHandler.cs b/v2rayN/v2rayN/Handler/MainFormHandler.cs index e2f37a2a48..8547277bfe 100644 --- a/v2rayN/v2rayN/Handler/MainFormHandler.cs +++ b/v2rayN/v2rayN/Handler/MainFormHandler.cs @@ -156,71 +156,7 @@ public void Export2ClientConfig(ProfileItem item, Config config) } } - public void UpdateTask(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 UpdateHandle(); - 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 UpdateHandle(); - 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); - } - } - - public void RegisterGlobalHotkey(Config config, Action handler, Action update) + public void RegisterGlobalHotkey(Config config, Action handler, Action? update) { HotkeyHandler.Instance.UpdateViewEvent += update; HotkeyHandler.Instance.HotkeyTriggerEvent += handler; @@ -240,7 +176,7 @@ public void RegisterSystemColorSet(Config config, Window window, Action up { if (wParam == IntPtr.Zero && Marshal.PtrToStringUni(lParam) == "ImmersiveColorSet") { - update(!Utils.IsLightTheme()); + update(!WindowsUtils.IsLightTheme()); } } } diff --git a/v2rayN/v2rayN/Models/ConfigItems.cs b/v2rayN/v2rayN/Models/ConfigItems.cs index 031b013448..b7c9c46fed 100644 --- a/v2rayN/v2rayN/Models/ConfigItems.cs +++ b/v2rayN/v2rayN/Models/ConfigItems.cs @@ -1,5 +1,4 @@ -using System.Windows.Input; -using v2rayN.Enums; +using v2rayN.Enums; namespace v2rayN.Models { @@ -152,7 +151,7 @@ public class KeyEventItem public bool Shift { get; set; } - public Key? KeyCode { get; set; } + public int? KeyCode { get; set; } } [Serializable] diff --git a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs index fcff69a4ab..50afd9b56f 100644 --- a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs @@ -3,13 +3,10 @@ using ReactiveUI.Fody.Helpers; using Splat; using System.Diagnostics; -using System.Drawing; using System.IO; using System.Reactive; using System.Reactive.Linq; using System.Text; -using System.Windows; -using System.Windows.Media; using v2rayN.Base; using v2rayN.Enums; using v2rayN.Handler; @@ -95,12 +92,6 @@ public class MainWindowViewModel : MyReactiveObject public ReactiveCommand NotifyLeftClickCmd { get; } - [Reactive] - public Icon NotifyIcon { get; set; } - - [Reactive] - public ImageSource AppIcon { get; set; } - #endregion Menu #region System Proxy @@ -259,9 +250,9 @@ public MainWindowViewModel(Func? updateView) { AddServerViaClipboard(); }); - AddServerViaScanCmd = ReactiveCommand.CreateFromTask(() => + AddServerViaScanCmd = ReactiveCommand.Create(() => { - return ScanScreenTaskAsync(); + _updateView?.Invoke(EViewAction.ScanScreenTask, null); }); //Subscription @@ -390,9 +381,7 @@ private void Init() StatisticsHandler.Instance.Init(_config, UpdateStatisticsHandler); } - MainFormHandler.Instance.UpdateTask(_config, UpdateTaskHandler); - MainFormHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, UpdateTaskHandler); - + RegUpdateTask(_config, UpdateTaskHandler); RefreshRoutingsMenu(); //RefreshServers(); @@ -463,32 +452,6 @@ public void SetStatisticsResult(ServerSpeedItem update) } } - private void OnHotkeyHandler(EGlobalHotkey e) - { - switch (e) - { - case EGlobalHotkey.ShowForm: - _updateView?.Invoke(EViewAction.ShowHideWindow, null); - break; - - case EGlobalHotkey.SystemProxyClear: - SetListenerType(ESysProxyType.ForcedClear); - break; - - case EGlobalHotkey.SystemProxySet: - SetListenerType(ESysProxyType.ForcedChange); - break; - - case EGlobalHotkey.SystemProxyUnchanged: - SetListenerType(ESysProxyType.Unchanged); - break; - - case EGlobalHotkey.SystemProxyPac: - SetListenerType(ESysProxyType.Pac); - break; - } - } - public void MyAppExit(bool blWindowsShutDown) { try @@ -517,7 +480,7 @@ public void MyAppExit(bool blWindowsShutDown) catch { } finally { - Application.Current.Shutdown(); + _updateView?.Invoke(EViewAction.Shutdown, null); } } @@ -613,7 +576,7 @@ public void AddServer(bool blNew, EConfigType eConfigType) public void AddServerViaClipboard() { - var clipboardData = Utils.GetClipboardData(); + var clipboardData = WindowsUtils.GetClipboardData(); int ret = ConfigHandler.AddBatchServers(_config, clipboardData!, _config.subIndexId, false); if (ret > 0) { @@ -623,18 +586,8 @@ public void AddServerViaClipboard() } } - public async Task ScanScreenTaskAsync() + public void ScanScreenTaskAsync(string result) { - _updateView?.Invoke(EViewAction.ShowHideWindow, false); - - var dpiXY = QRCodeHelper.GetDpiXY(Application.Current.MainWindow); - string result = await Task.Run(() => - { - return QRCodeHelper.ScanScreen(dpiXY.Item1, dpiXY.Item2); - }); - - _updateView?.Invoke(EViewAction.ShowHideWindow, true); - if (Utils.IsNullOrEmpty(result)) { _noticeHandler?.Enqueue(ResUI.NoValidQRcodeFound); @@ -869,6 +822,12 @@ private async Task LoadCore() { await Task.Run(() => { + if (_config.tunModeItem.enableTun) + { + Thread.Sleep(1000); + WindowsUtils.RemoveTunDevice(); + } + var node = ConfigHandler.GetDefaultServer(_config); _coreHandler.LoadCore(node); }); @@ -914,8 +873,7 @@ private void ChangeSystemProxyStatus(ESysProxyType type, bool blChange) if (blChange) { - NotifyIcon = MainFormHandler.Instance.GetNotifyIcon(_config); - AppIcon = MainFormHandler.Instance.GetAppIcon(_config); + _updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null); } } @@ -966,8 +924,7 @@ private void RoutingSelectedChanged(bool c) { _noticeHandler?.SendMessage(ResUI.TipChangeRouting, true); Reload(); - NotifyIcon = MainFormHandler.Instance.GetNotifyIcon(_config); - AppIcon = MainFormHandler.Instance.GetAppIcon(_config); + _updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null); } } @@ -1054,5 +1011,73 @@ private void AutoHideStartup() } #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 UpdateHandle(); + 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 UpdateHandle(); + 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 a504d20d2a..68f1761392 100644 --- a/v2rayN/v2rayN/ViewModels/ProfilesViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/ProfilesViewModel.cs @@ -739,7 +739,7 @@ public void Export2ShareUrl() } if (sb.Length > 0) { - Utils.SetClipboardData(sb.ToString()); + WindowsUtils.SetClipboardData(sb.ToString()); _noticeHandler?.SendMessage(ResUI.BatchExportURLSuccessfully); } } diff --git a/v2rayN/v2rayN/ViewModels/RoutingRuleSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/RoutingRuleSettingViewModel.cs index 17715d932f..b1b08f7c01 100644 --- a/v2rayN/v2rayN/ViewModels/RoutingRuleSettingViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/RoutingRuleSettingViewModel.cs @@ -202,7 +202,7 @@ public void RuleExportSelected() } if (lst.Count > 0) { - Utils.SetClipboardData(JsonUtils.Serialize(lst)); + WindowsUtils.SetClipboardData(JsonUtils.Serialize(lst)); //_noticeHandler?.Enqueue(ResUI.OperationSuccess")); } } @@ -283,7 +283,7 @@ private void ImportRulesFromFile() private void ImportRulesFromClipboard() { - var clipboardData = Utils.GetClipboardData(); + var clipboardData = WindowsUtils.GetClipboardData(); if (AddBatchRoutingRules(SelectedRouting, clipboardData) == 0) { RefreshRulesItems(); diff --git a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs index 8070a86ae9..8e17e499e0 100644 --- a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs @@ -50,7 +50,7 @@ private void RestoreUI() { if (FollowSystemTheme) { - ModifyTheme(!Utils.IsLightTheme()); + ModifyTheme(!WindowsUtils.IsLightTheme()); } else { @@ -104,7 +104,7 @@ private void BindingUI() ConfigHandler.SaveConfig(_config); if (FollowSystemTheme) { - ModifyTheme(!Utils.IsLightTheme()); + ModifyTheme(!WindowsUtils.IsLightTheme()); } else { @@ -173,8 +173,7 @@ public void ModifyTheme(bool isDarkTheme) theme.SetBaseTheme(isDarkTheme ? BaseTheme.Dark : BaseTheme.Light); _paletteHelper.SetTheme(theme); - - Utils.SetDarkBorder(Application.Current.MainWindow, isDarkTheme); + WindowsUtils.SetDarkBorder(Application.Current.MainWindow, isDarkTheme); } public void ChangePrimaryColor(System.Windows.Media.Color color) diff --git a/v2rayN/v2rayN/Views/AddServer2Window.xaml.cs b/v2rayN/v2rayN/Views/AddServer2Window.xaml.cs index 1ce39b9e75..43a22f0dbb 100644 --- a/v2rayN/v2rayN/Views/AddServer2Window.xaml.cs +++ b/v2rayN/v2rayN/Views/AddServer2Window.xaml.cs @@ -38,8 +38,7 @@ public AddServer2Window(ProfileItem profileItem) this.BindCommand(ViewModel, vm => vm.EditServerCmd, v => v.btnEdit).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveServerCmd, v => v.btnSave).DisposeWith(disposables); }); - - Utils.SetDarkBorder(this, LazyConfig.Instance.GetConfig().uiItem.followSystemTheme ? !Utils.IsLightTheme() : LazyConfig.Instance.GetConfig().uiItem.colorModeDark); + WindowsUtils.SetDarkBorder(this, LazyConfig.Instance.GetConfig().uiItem.followSystemTheme ? !WindowsUtils.IsLightTheme() : LazyConfig.Instance.GetConfig().uiItem.colorModeDark); } private bool UpdateViewHandler(EViewAction action, object? obj) diff --git a/v2rayN/v2rayN/Views/GlobalHotkeySettingWindow.xaml.cs b/v2rayN/v2rayN/Views/GlobalHotkeySettingWindow.xaml.cs index 8fbe8f2f8e..b12bb6cc20 100644 --- a/v2rayN/v2rayN/Views/GlobalHotkeySettingWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/GlobalHotkeySettingWindow.xaml.cs @@ -30,7 +30,7 @@ public GlobalHotkeySettingWindow() HotkeyHandler.Instance.IsPause = true; this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false; - Utils.SetDarkBorder(this, _config.uiItem.followSystemTheme ? !Utils.IsLightTheme() : _config.uiItem.colorModeDark); + WindowsUtils.SetDarkBorder(this, _config.uiItem.followSystemTheme ? !WindowsUtils.IsLightTheme() : _config.uiItem.colorModeDark); InitData(); } @@ -52,7 +52,7 @@ private void TxtGlobalHotkey_PreviewKeyDown(object sender, KeyEventArgs e) e.Handled = true; var _ModifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift, Key.RightShift, Key.LeftAlt, Key.RightAlt, Key.LWin, Key.RWin}; - _TextBoxKeyEventItem[sender].KeyCode = e.Key == Key.System ? (_ModifierKeys.Contains(e.SystemKey) ? Key.None : e.SystemKey) : (_ModifierKeys.Contains(e.Key) ? Key.None : e.Key); + _TextBoxKeyEventItem[sender].KeyCode = (int)(e.Key == Key.System ? (_ModifierKeys.Contains(e.SystemKey) ? Key.None : e.SystemKey) : (_ModifierKeys.Contains(e.Key) ? Key.None : e.Key)); _TextBoxKeyEventItem[sender].Alt = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt; _TextBoxKeyEventItem[sender].Control = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control; _TextBoxKeyEventItem[sender].Shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift; @@ -78,8 +78,8 @@ private string KeyEventItemToString(KeyEventItem item) if (item.Control) res.Append($"{ModifierKeys.Control}+"); if (item.Shift) res.Append($"{ModifierKeys.Shift}+"); if (item.Alt) res.Append($"{ModifierKeys.Alt}+"); - if (item.KeyCode != null && item.KeyCode != Key.None) - res.Append($"{item.KeyCode}"); + if (item.KeyCode != null && (Key)item.KeyCode != Key.None) + res.Append($"{(Key)item.KeyCode}"); return res.ToString(); } @@ -88,7 +88,7 @@ private void BindingData() { foreach (var item in _TextBoxKeyEventItem) { - if (item.Value.KeyCode != null && item.Value.KeyCode != Key.None) + if (item.Value.KeyCode != null && (Key)item.Value.KeyCode != Key.None) { (item.Key as TextBox)!.Text = KeyEventItemToString(item.Value); } @@ -121,7 +121,7 @@ private void btnReset_Click(object sender, RoutedEventArgs e) _TextBoxKeyEventItem[k].Alt = false; _TextBoxKeyEventItem[k].Control = false; _TextBoxKeyEventItem[k].Shift = false; - _TextBoxKeyEventItem[k].KeyCode = Key.None; + _TextBoxKeyEventItem[k].KeyCode = (int)Key.None; } BindingData(); } diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml.cs b/v2rayN/v2rayN/Views/MainWindow.xaml.cs index d93a3227ae..bfe29129ce 100644 --- a/v2rayN/v2rayN/Views/MainWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/MainWindow.xaml.cs @@ -37,6 +37,8 @@ public MainWindow() ViewModel = new MainWindowViewModel(UpdateViewHandler); Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel)); + MainFormHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null); + this.WhenActivated(disposables => { //servers @@ -106,10 +108,8 @@ public MainWindow() this.BindCommand(ViewModel, vm => vm.SubUpdateCmd, v => v.menuSubUpdate2).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SubUpdateViaProxyCmd, v => v.menuSubUpdateViaProxy2).DisposeWith(disposables); - this.OneWayBind(ViewModel, vm => vm.NotifyIcon, v => v.tbNotify.Icon).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.RunningServerToolTipText, v => v.tbNotify.ToolTipText).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.NotifyLeftClickCmd, v => v.tbNotify.LeftClickCommand).DisposeWith(disposables); - this.OneWayBind(ViewModel, vm => vm.AppIcon, v => v.Icon).DisposeWith(disposables); //status bar this.OneWayBind(ViewModel, vm => vm.InboundDisplay, v => v.txtInboundDisplay.Text).DisposeWith(disposables); @@ -183,6 +183,8 @@ public MainWindow() AddHelpMenuItem(); } + #region Event + private bool UpdateViewHandler(EViewAction action, object? obj) { switch (action) @@ -246,12 +248,52 @@ private bool UpdateViewHandler(EViewAction action, object? obj) ViewModel?.RefreshServersBiz(); }), DispatcherPriority.Normal); break; + + case EViewAction.DispatcherRefreshIcon: + Application.Current?.Dispatcher.Invoke((() => + { + tbNotify.Icon = MainFormHandler.Instance.GetNotifyIcon(_config); + this.Icon = MainFormHandler.Instance.GetAppIcon(_config); + }), DispatcherPriority.Normal); + break; + + case EViewAction.Shutdown: + Application.Current.Shutdown(); + break; + + case EViewAction ScanScreenTask: + ScanScreenTaskAsync().ContinueWith(_ => { }); + break; } return true; } - #region Event + private void OnHotkeyHandler(EGlobalHotkey e) + { + switch (e) + { + case EGlobalHotkey.ShowForm: + ShowHideWindow(null); + break; + + case EGlobalHotkey.SystemProxyClear: + ViewModel?.SetListenerType(ESysProxyType.ForcedClear); + break; + + case EGlobalHotkey.SystemProxySet: + ViewModel?.SetListenerType(ESysProxyType.ForcedChange); + break; + + case EGlobalHotkey.SystemProxyUnchanged: + ViewModel?.SetListenerType(ESysProxyType.Unchanged); + break; + + case EGlobalHotkey.SystemProxyPac: + ViewModel?.SetListenerType(ESysProxyType.Pac); + break; + } + } private void MainWindow_Closing(object? sender, CancelEventArgs e) { @@ -286,7 +328,7 @@ private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e) break; case Key.S: - ViewModel?.ScanScreenTaskAsync().ContinueWith(_ => { }); + ScanScreenTaskAsync().ContinueWith(_ => { }); break; } } @@ -320,6 +362,21 @@ private void menuSettingsSetUWP_Click(object sender, RoutedEventArgs e) Utils.ProcessStart(Utils.GetBinPath("EnableLoopback.exe")); } + public async Task ScanScreenTaskAsync() + { + ShowHideWindow(false); + + var dpiXY = QRCodeHelper.GetDpiXY(Application.Current.MainWindow); + string result = await Task.Run(() => + { + return QRCodeHelper.ScanScreen(dpiXY.Item1, dpiXY.Item2); + }); + + ShowHideWindow(true); + + ViewModel?.ScanScreenTaskAsync(result); + } + #endregion Event #region UI diff --git a/v2rayN/v2rayN/Views/MsgView.xaml.cs b/v2rayN/v2rayN/Views/MsgView.xaml.cs index e00574a7ce..a8877cbe7e 100644 --- a/v2rayN/v2rayN/Views/MsgView.xaml.cs +++ b/v2rayN/v2rayN/Views/MsgView.xaml.cs @@ -99,13 +99,13 @@ private void menuMsgViewSelectAll_Click(object sender, System.Windows.RoutedEven private void menuMsgViewCopy_Click(object sender, System.Windows.RoutedEventArgs e) { var data = txtMsg.SelectedText.TrimEx(); - Utils.SetClipboardData(data); + WindowsUtils.SetClipboardData(data); } private void menuMsgViewCopyAll_Click(object sender, System.Windows.RoutedEventArgs e) { var data = txtMsg.Text; - Utils.SetClipboardData(data); + WindowsUtils.SetClipboardData(data); } private void menuMsgViewClear_Click(object sender, System.Windows.RoutedEventArgs e)