From 671678724b3cc2186f9d2370350bbb80dcdb0b6c Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Wed, 24 Sep 2025 10:57:06 +0800 Subject: [PATCH] Optimization and improvement, using event subscribers --- v2rayN/ServiceLib/Enums/EViewAction.cs | 1 - v2rayN/ServiceLib/Handler/AppEvents.cs | 6 +++ v2rayN/ServiceLib/Manager/AppManager.cs | 6 +++ .../ViewModels/CheckUpdateViewModel.cs | 6 +-- .../ViewModels/MainWindowViewModel.cs | 46 +++++++++++-------- .../ViewModels/ProfilesViewModel.cs | 3 +- .../ViewModels/StatusBarViewModel.cs | 28 +++++------ v2rayN/v2rayN.Desktop/App.axaml.cs | 15 ++---- .../v2rayN.Desktop/Views/MainWindow.axaml.cs | 35 +++++++------- v2rayN/v2rayN/Views/MainWindow.xaml.cs | 46 +++++++++---------- 10 files changed, 95 insertions(+), 97 deletions(-) diff --git a/v2rayN/ServiceLib/Enums/EViewAction.cs b/v2rayN/ServiceLib/Enums/EViewAction.cs index 2c47d31d..075439fd 100644 --- a/v2rayN/ServiceLib/Enums/EViewAction.cs +++ b/v2rayN/ServiceLib/Enums/EViewAction.cs @@ -12,7 +12,6 @@ public enum EViewAction ProfilesFocus, ShareSub, ShareServer, - ShowHideWindow, ScanScreenTask, ScanImageTask, BrowseServer, diff --git a/v2rayN/ServiceLib/Handler/AppEvents.cs b/v2rayN/ServiceLib/Handler/AppEvents.cs index a4c2917d..bda78922 100644 --- a/v2rayN/ServiceLib/Handler/AppEvents.cs +++ b/v2rayN/ServiceLib/Handler/AppEvents.cs @@ -5,6 +5,12 @@ namespace ServiceLib.Handler; public static class AppEvents { + public static readonly Subject ReloadRequested = new(); + public static readonly Subject ShowHideWindowRequested = new(); + public static readonly Subject AddServerViaScanRequested = new(); + public static readonly Subject AddServerViaClipboardRequested = new(); + public static readonly Subject SubscriptionsUpdateRequested = new(); + public static readonly Subject ProfilesRefreshRequested = new(); public static readonly Subject SubscriptionsRefreshRequested = new(); public static readonly Subject ProxiesReloadRequested = new(); diff --git a/v2rayN/ServiceLib/Manager/AppManager.cs b/v2rayN/ServiceLib/Manager/AppManager.cs index 33125289..57238b15 100644 --- a/v2rayN/ServiceLib/Manager/AppManager.cs +++ b/v2rayN/ServiceLib/Manager/AppManager.cs @@ -122,6 +122,12 @@ public sealed class AppManager AppEvents.ShutdownRequested.OnNext(byUser); } + public async Task RebootAsAdmin() + { + ProcUtils.RebootAsAdmin(); + await AppManager.Instance.AppExitAsync(true); + } + #endregion App #region Config diff --git a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs index 5ec1f80b..171cb467 100644 --- a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs @@ -2,11 +2,9 @@ using System.Reactive; using System.Reactive.Disposables; using System.Reactive.Linq; using System.Runtime.InteropServices; -using DynamicData; using DynamicData.Binding; using ReactiveUI; using ReactiveUI.Fody.Helpers; -using Splat; namespace ServiceLib.ViewModels; @@ -225,11 +223,11 @@ public class CheckUpdateViewModel : MyReactiveObject { if (blReload) { - Locator.Current.GetService()?.Reload(); + AppEvents.ReloadRequested.OnNext(Unit.Default); } else { - Locator.Current.GetService()?.CloseCore(); + await CoreManager.Instance.CoreStop(); } } diff --git a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs index 3492670c..ba5de790 100644 --- a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs @@ -1,5 +1,6 @@ using System.Reactive; using System.Reactive.Concurrency; +using System.Reactive.Linq; using ReactiveUI; using ReactiveUI.Fody.Helpers; @@ -183,7 +184,7 @@ public class MainWindowViewModel : MyReactiveObject }); RebootAsAdminCmd = ReactiveCommand.CreateFromTask(async () => { - await RebootAsAdmin(); + await AppManager.Instance.RebootAsAdmin(); }); ClearServerStatisticsCmd = ReactiveCommand.CreateFromTask(async () => { @@ -216,6 +217,30 @@ public class MainWindowViewModel : MyReactiveObject #endregion WhenAnyValue && ReactiveCommand + #region AppEvents + + AppEvents.ReloadRequested + .AsObservable() + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(async _ => await Reload()); + + AppEvents.AddServerViaScanRequested + .AsObservable() + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(async _ => await AddServerViaScanAsync()); + + AppEvents.AddServerViaClipboardRequested + .AsObservable() + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(async _ => await AddServerViaClipboardAsync(null)); + + AppEvents.SubscriptionsUpdateRequested + .AsObservable() + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(async blProxy => await UpdateSubscriptionProcess("", blProxy)); + + #endregion AppEvents + _ = Init(); } @@ -281,11 +306,6 @@ public class MainWindowViewModel : MyReactiveObject AppEvents.DispatcherStatisticsRequested.OnNext(update); } - public void ShowHideWindow(bool? blShow) - { - _updateView?.Invoke(EViewAction.ShowHideWindow, blShow); - } - #endregion Actions #region Servers && Groups @@ -465,12 +485,6 @@ public class MainWindowViewModel : MyReactiveObject } } - public async Task RebootAsAdmin() - { - ProcUtils.RebootAsAdmin(); - await AppManager.Instance.AppExitAsync(true); - } - private async Task ClearServerStatistics() { await StatisticsManager.Instance.ClearAllServerStatistics(); @@ -547,17 +561,11 @@ public class MainWindowViewModel : MyReactiveObject await CoreManager.Instance.LoadCore(node); } - public async Task CloseCore() - { - await ConfigHandler.SaveConfig(_config); - await CoreManager.Instance.CoreStop(); - } - private async Task AutoHideStartup() { if (_config.UiItem.AutoHideStartup) { - ShowHideWindow(false); + AppEvents.ShowHideWindowRequested.OnNext(false); } await Task.CompletedTask; } diff --git a/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs b/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs index 87e1d78f..fcf3450d 100644 --- a/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs @@ -6,7 +6,6 @@ using DynamicData; using DynamicData.Binding; using ReactiveUI; using ReactiveUI.Fody.Helpers; -using Splat; namespace ServiceLib.ViewModels; @@ -276,7 +275,7 @@ public class ProfilesViewModel : MyReactiveObject private void Reload() { - Locator.Current.GetService()?.Reload(); + AppEvents.ReloadRequested.OnNext(Unit.Default); } public async Task SetSpeedTestResult(SpeedTestResult result) diff --git a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs index ee66351c..6dc795ef 100644 --- a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs @@ -5,7 +5,6 @@ using System.Text; using DynamicData.Binding; using ReactiveUI; using ReactiveUI.Fody.Helpers; -using Splat; namespace ServiceLib.ViewModels; @@ -149,17 +148,17 @@ public class StatusBarViewModel : MyReactiveObject NotifyLeftClickCmd = ReactiveCommand.CreateFromTask(async () => { - Locator.Current.GetService()?.ShowHideWindow(null); + AppEvents.ShowHideWindowRequested.OnNext(null); await Task.CompletedTask; }); ShowWindowCmd = ReactiveCommand.CreateFromTask(async () => { - Locator.Current.GetService()?.ShowHideWindow(true); + AppEvents.ShowHideWindowRequested.OnNext(true); await Task.CompletedTask; }); HideWindowCmd = ReactiveCommand.CreateFromTask(async () => { - Locator.Current.GetService()?.ShowHideWindow(false); + AppEvents.ShowHideWindowRequested.OnNext(false); await Task.CompletedTask; }); @@ -275,23 +274,20 @@ public class StatusBarViewModel : MyReactiveObject private async Task AddServerViaClipboard() { - var service = Locator.Current.GetService(); - if (service != null) - await service.AddServerViaClipboardAsync(null); + AppEvents.AddServerViaClipboardRequested.OnNext(Unit.Default); + await Task.Delay(1000); } private async Task AddServerViaScan() { - var service = Locator.Current.GetService(); - if (service != null) - await service.AddServerViaScanAsync(); + AppEvents.AddServerViaScanRequested.OnNext(Unit.Default); + await Task.Delay(1000); } private async Task UpdateSubscriptionProcess(bool blProxy) { - var service = Locator.Current.GetService(); - if (service != null) - await service.UpdateSubscriptionProcess("", blProxy); + AppEvents.SubscriptionsUpdateRequested.OnNext(blProxy); + await Task.Delay(1000); } private async Task RefreshServersBiz() @@ -453,7 +449,7 @@ public class StatusBarViewModel : MyReactiveObject if (await ConfigHandler.SetDefaultRouting(_config, item) == 0) { NoticeManager.Instance.SendMessageEx(ResUI.TipChangeRouting); - Locator.Current.GetService()?.Reload(); + AppEvents.ReloadRequested.OnNext(Unit.Default); _updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null); } } @@ -486,7 +482,7 @@ public class StatusBarViewModel : MyReactiveObject if (Utils.IsWindows()) { _config.TunModeItem.EnableTun = false; - Locator.Current.GetService()?.RebootAsAdmin(); + await AppManager.Instance.RebootAsAdmin(); return; } else @@ -500,7 +496,7 @@ public class StatusBarViewModel : MyReactiveObject } } await ConfigHandler.SaveConfig(_config); - Locator.Current.GetService()?.Reload(); + AppEvents.ReloadRequested.OnNext(Unit.Default); } private bool AllowEnableTun() diff --git a/v2rayN/v2rayN.Desktop/App.axaml.cs b/v2rayN/v2rayN.Desktop/App.axaml.cs index 515354d5..fa4779cf 100644 --- a/v2rayN/v2rayN.Desktop/App.axaml.cs +++ b/v2rayN/v2rayN.Desktop/App.axaml.cs @@ -1,8 +1,7 @@ +using System.Reactive; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; -using Splat; -using v2rayN.Desktop.Common; using v2rayN.Desktop.Views; namespace v2rayN.Desktop; @@ -55,16 +54,8 @@ public partial class App : Application { if (desktop.MainWindow != null) { - var clipboardData = await AvaUtils.GetClipboardData(desktop.MainWindow); - if (clipboardData.IsNullOrEmpty()) - { - return; - } - var service = Locator.Current.GetService(); - if (service != null) - { - _ = service.AddServerViaClipboardAsync(clipboardData); - } + AppEvents.AddServerViaClipboardRequested.OnNext(Unit.Default); + await Task.Delay(1000); } } } diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs index eb884e4b..86bd5d7b 100644 --- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs @@ -10,7 +10,6 @@ using Avalonia.Threading; using DialogHostAvalonia; using MsBox.Avalonia.Enums; using ReactiveUI; -using Splat; using v2rayN.Desktop.Base; using v2rayN.Desktop.Common; using v2rayN.Desktop.Manager; @@ -40,7 +39,6 @@ public partial class MainWindow : WindowBase menuClose.Click += MenuClose_Click; ViewModel = new MainWindowViewModel(UpdateViewHandler); - Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel)); switch (_config.UiItem.MainGirdOrientation) { @@ -153,6 +151,12 @@ public partial class MainWindow : WindowBase .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(content => Shutdown(content)) .DisposeWith(disposables); + + AppEvents.ShowHideWindowRequested + .AsObservable() + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(blShow => ShowHideWindow(blShow)) + .DisposeWith(disposables); }); if (Utils.IsWindows()) @@ -221,12 +225,6 @@ public partial class MainWindow : WindowBase case EViewAction.SubSettingWindow: return await new SubSettingWindow().ShowDialog(this); - case EViewAction.ShowHideWindow: - Dispatcher.UIThread.Post(() => - ShowHideWindow((bool?)obj), - DispatcherPriority.Default); - break; - case EViewAction.ScanScreenTask: await ScanScreenTaskAsync(); break; @@ -236,11 +234,7 @@ public partial class MainWindow : WindowBase break; case EViewAction.AddServerViaClipboard: - var clipboardData = await AvaUtils.GetClipboardData(this); - if (clipboardData.IsNotEmpty() && ViewModel != null) - { - await ViewModel.AddServerViaClipboardAsync(clipboardData); - } + await AddServerViaClipboardAsync(); break; } @@ -295,11 +289,7 @@ public partial class MainWindow : WindowBase switch (e.Key) { case Key.V: - var clipboardData = await AvaUtils.GetClipboardData(this); - if (clipboardData.IsNotEmpty() && ViewModel != null) - { - await ViewModel.AddServerViaClipboardAsync(clipboardData); - } + await AddServerViaClipboardAsync(); break; case Key.S: @@ -326,6 +316,15 @@ public partial class MainWindow : WindowBase ProcUtils.ProcessStart(Utils.GetBinPath("EnableLoopback.exe")); } + public async Task AddServerViaClipboardAsync() + { + var clipboardData = await AvaUtils.GetClipboardData(this); + if (clipboardData.IsNotEmpty() && ViewModel != null) + { + await ViewModel.AddServerViaClipboardAsync(clipboardData); + } + } + public async Task ScanScreenTaskAsync() { //ShowHideWindow(false); diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml.cs b/v2rayN/v2rayN/Views/MainWindow.xaml.cs index 28073be8..1d0d530c 100644 --- a/v2rayN/v2rayN/Views/MainWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/MainWindow.xaml.cs @@ -6,10 +6,8 @@ using System.Windows.Controls; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; -using System.Windows.Threading; using MaterialDesignThemes.Wpf; using ReactiveUI; -using Splat; using v2rayN.Manager; namespace v2rayN.Views; @@ -37,7 +35,6 @@ public partial class MainWindow menuBackupAndRestore.Click += MenuBackupAndRestore_Click; ViewModel = new MainWindowViewModel(UpdateViewHandler); - Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel)); switch (_config.UiItem.MainGirdOrientation) { @@ -146,10 +143,16 @@ public partial class MainWindow .DisposeWith(disposables); AppEvents.ShutdownRequested - .AsObservable() - .ObserveOn(RxApp.MainThreadScheduler) - .Subscribe(content => Shutdown(content)) - .DisposeWith(disposables); + .AsObservable() + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(content => Shutdown(content)) + .DisposeWith(disposables); + + AppEvents.ShowHideWindowRequested + .AsObservable() + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(blShow => ShowHideWindow(blShow)) + .DisposeWith(disposables); }); this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}"; @@ -210,13 +213,6 @@ public partial class MainWindow case EViewAction.SubSettingWindow: return (new SubSettingWindow().ShowDialog() ?? false); - case EViewAction.ShowHideWindow: - Application.Current?.Dispatcher.Invoke((() => - { - ShowHideWindow((bool?)obj); - }), DispatcherPriority.Normal); - break; - case EViewAction.ScanScreenTask: await ScanScreenTaskAsync(); break; @@ -226,11 +222,7 @@ public partial class MainWindow break; case EViewAction.AddServerViaClipboard: - var clipboardData = WindowsUtils.GetClipboardData(); - if (clipboardData.IsNotEmpty()) - { - ViewModel?.AddServerViaClipboardAsync(clipboardData); - } + await AddServerViaClipboardAsync(); break; } @@ -283,12 +275,7 @@ public partial class MainWindow { return; } - - var clipboardData = WindowsUtils.GetClipboardData(); - if (clipboardData.IsNotEmpty()) - { - ViewModel?.AddServerViaClipboardAsync(clipboardData); - } + AddServerViaClipboardAsync().ContinueWith(_ => { }); break; @@ -322,6 +309,15 @@ public partial class MainWindow ProcUtils.ProcessStart(Utils.GetBinPath("EnableLoopback.exe")); } + public async Task AddServerViaClipboardAsync() + { + var clipboardData = WindowsUtils.GetClipboardData(); + if (clipboardData.IsNotEmpty() && ViewModel != null) + { + await ViewModel.AddServerViaClipboardAsync(clipboardData); + } + } + private async Task ScanScreenTaskAsync() { ShowHideWindow(false);