From d86003df55cff21199eb251de3bd2da984ec899b Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Thu, 25 Sep 2025 10:56:10 +0800 Subject: [PATCH] Optimize and improve the Subject --- v2rayN/ServiceLib/Events/AppEvents.cs | 32 ++++++++++++++++++ v2rayN/ServiceLib/Events/EventChannel.cs | 29 ++++++++++++++++ v2rayN/ServiceLib/GlobalUsings.cs | 1 + v2rayN/ServiceLib/Handler/AppEvents.cs | 33 ------------------- v2rayN/ServiceLib/Manager/AppManager.cs | 4 +-- v2rayN/ServiceLib/Manager/NoticeManager.cs | 4 +-- .../ViewModels/CheckUpdateViewModel.cs | 2 +- .../ViewModels/MainWindowViewModel.cs | 20 +++++------ .../ViewModels/ProfilesViewModel.cs | 4 +-- .../ViewModels/StatusBarViewModel.cs | 18 +++++----- v2rayN/v2rayN.Desktop/App.axaml.cs | 2 +- v2rayN/v2rayN.Desktop/GlobalUsings.cs | 1 + .../v2rayN.Desktop/Views/MainWindow.axaml.cs | 2 +- v2rayN/v2rayN/GlobalUsings.cs | 1 + v2rayN/v2rayN/Views/MainWindow.xaml.cs | 2 +- 15 files changed, 93 insertions(+), 62 deletions(-) create mode 100644 v2rayN/ServiceLib/Events/AppEvents.cs create mode 100644 v2rayN/ServiceLib/Events/EventChannel.cs delete mode 100644 v2rayN/ServiceLib/Handler/AppEvents.cs diff --git a/v2rayN/ServiceLib/Events/AppEvents.cs b/v2rayN/ServiceLib/Events/AppEvents.cs new file mode 100644 index 00000000..45de4de1 --- /dev/null +++ b/v2rayN/ServiceLib/Events/AppEvents.cs @@ -0,0 +1,32 @@ +using System.Reactive; + +namespace ServiceLib.Events; + +public static class AppEvents +{ + public static readonly EventChannel ReloadRequested = new(); + public static readonly EventChannel ShowHideWindowRequested = new(); + public static readonly EventChannel AddServerViaScanRequested = new(); + public static readonly EventChannel AddServerViaClipboardRequested = new(); + public static readonly EventChannel SubscriptionsUpdateRequested = new(); + + public static readonly EventChannel ProfilesRefreshRequested = new(); + public static readonly EventChannel SubscriptionsRefreshRequested = new(); + public static readonly EventChannel ProxiesReloadRequested = new(); + public static readonly EventChannel DispatcherStatisticsRequested = new(); + + public static readonly EventChannel SendSnackMsgRequested = new(); + public static readonly EventChannel SendMsgViewRequested = new(); + + public static readonly EventChannel AppExitRequested = new(); + public static readonly EventChannel ShutdownRequested = new(); + + public static readonly EventChannel AdjustMainLvColWidthRequested = new(); + + public static readonly EventChannel SetDefaultServerRequested = new(); + + public static readonly EventChannel RoutingsMenuRefreshRequested = new(); + public static readonly EventChannel TestServerRequested = new(); + public static readonly EventChannel InboundDisplayRequested = new(); + public static readonly EventChannel SysProxyChangeRequested = new(); +} diff --git a/v2rayN/ServiceLib/Events/EventChannel.cs b/v2rayN/ServiceLib/Events/EventChannel.cs new file mode 100644 index 00000000..c3c58f3e --- /dev/null +++ b/v2rayN/ServiceLib/Events/EventChannel.cs @@ -0,0 +1,29 @@ +using System.Reactive; +using System.Reactive.Linq; +using System.Reactive.Subjects; + +namespace ServiceLib.Events; + +public sealed class EventChannel +{ + private readonly ISubject _subject = Subject.Synchronize(new Subject()); + + public IObservable AsObservable() + { + return _subject.AsObservable(); + } + + public void Publish(T value) + { + _subject.OnNext(value); + } + + public void Publish() + { + if (typeof(T) != typeof(Unit)) + { + throw new InvalidOperationException("Publish() without value is only valid for EventChannel."); + } + _subject.OnNext((T)(object)Unit.Default); + } +} diff --git a/v2rayN/ServiceLib/GlobalUsings.cs b/v2rayN/ServiceLib/GlobalUsings.cs index 9a78c73b..a952f4a8 100644 --- a/v2rayN/ServiceLib/GlobalUsings.cs +++ b/v2rayN/ServiceLib/GlobalUsings.cs @@ -1,6 +1,7 @@ global using ServiceLib.Base; global using ServiceLib.Common; global using ServiceLib.Enums; +global using ServiceLib.Events; global using ServiceLib.Handler; global using ServiceLib.Helper; global using ServiceLib.Manager; diff --git a/v2rayN/ServiceLib/Handler/AppEvents.cs b/v2rayN/ServiceLib/Handler/AppEvents.cs deleted file mode 100644 index bda78922..00000000 --- a/v2rayN/ServiceLib/Handler/AppEvents.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reactive; -using System.Reactive.Subjects; - -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(); - public static readonly Subject DispatcherStatisticsRequested = new(); - - public static readonly Subject SendSnackMsgRequested = new(); - public static readonly Subject SendMsgViewRequested = new(); - - public static readonly Subject AppExitRequested = new(); - public static readonly Subject ShutdownRequested = new(); - - public static readonly Subject AdjustMainLvColWidthRequested = new(); - - public static readonly Subject SetDefaultServerRequested = new(); - - public static readonly Subject RoutingsMenuRefreshRequested = new(); - public static readonly Subject TestServerRequested = new(); - public static readonly Subject InboundDisplayRequested = new(); - public static readonly Subject SysProxyChangeRequested = new(); -} diff --git a/v2rayN/ServiceLib/Manager/AppManager.cs b/v2rayN/ServiceLib/Manager/AppManager.cs index 57238b15..a0518d21 100644 --- a/v2rayN/ServiceLib/Manager/AppManager.cs +++ b/v2rayN/ServiceLib/Manager/AppManager.cs @@ -96,7 +96,7 @@ public sealed class AppManager Logging.SaveLog("AppExitAsync Begin"); await SysProxyHandler.UpdateSysProxy(_config, true); - AppEvents.AppExitRequested.OnNext(Unit.Default); + AppEvents.AppExitRequested.Publish(); await Task.Delay(50); //Wait for AppExitRequested to be processed await ConfigHandler.SaveConfig(_config); @@ -119,7 +119,7 @@ public sealed class AppManager public void Shutdown(bool byUser) { - AppEvents.ShutdownRequested.OnNext(byUser); + AppEvents.ShutdownRequested.Publish(byUser); } public async Task RebootAsAdmin() diff --git a/v2rayN/ServiceLib/Manager/NoticeManager.cs b/v2rayN/ServiceLib/Manager/NoticeManager.cs index f9e149ed..da034f02 100644 --- a/v2rayN/ServiceLib/Manager/NoticeManager.cs +++ b/v2rayN/ServiceLib/Manager/NoticeManager.cs @@ -11,7 +11,7 @@ public class NoticeManager { return; } - AppEvents.SendSnackMsgRequested.OnNext(content); + AppEvents.SendSnackMsgRequested.Publish(content); } public void SendMessage(string? content) @@ -20,7 +20,7 @@ public class NoticeManager { return; } - AppEvents.SendMsgViewRequested.OnNext(content); + AppEvents.SendMsgViewRequested.Publish(content); } public void SendMessageEx(string? content) diff --git a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs index 171cb467..ade01d3c 100644 --- a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs @@ -223,7 +223,7 @@ public class CheckUpdateViewModel : MyReactiveObject { if (blReload) { - AppEvents.ReloadRequested.OnNext(Unit.Default); + AppEvents.ReloadRequested.Publish(); } else { diff --git a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs index ba5de790..be8898ae 100644 --- a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs @@ -292,7 +292,7 @@ public class MainWindowViewModel : MyReactiveObject } if (_config.UiItem.EnableAutoAdjustMainLvColWidth) { - AppEvents.AdjustMainLvColWidthRequested.OnNext(Unit.Default); + AppEvents.AdjustMainLvColWidthRequested.Publish(); } } } @@ -303,7 +303,7 @@ public class MainWindowViewModel : MyReactiveObject { return; } - AppEvents.DispatcherStatisticsRequested.OnNext(update); + AppEvents.DispatcherStatisticsRequested.Publish(update); } #endregion Actions @@ -312,14 +312,14 @@ public class MainWindowViewModel : MyReactiveObject private async Task RefreshServers() { - AppEvents.ProfilesRefreshRequested.OnNext(Unit.Default); + AppEvents.ProfilesRefreshRequested.Publish(); await Task.Delay(200); } private void RefreshSubscriptions() { - AppEvents.SubscriptionsRefreshRequested.OnNext(Unit.Default); + AppEvents.SubscriptionsRefreshRequested.Publish(); } #endregion Servers && Groups @@ -451,7 +451,7 @@ public class MainWindowViewModel : MyReactiveObject var ret = await _updateView?.Invoke(EViewAction.OptionSettingWindow, null); if (ret == true) { - AppEvents.InboundDisplayRequested.OnNext(Unit.Default); + AppEvents.InboundDisplayRequested.Publish(); await Reload(); } } @@ -462,7 +462,7 @@ public class MainWindowViewModel : MyReactiveObject if (ret == true) { await ConfigHandler.InitBuiltinRouting(_config); - AppEvents.RoutingsMenuRefreshRequested.OnNext(Unit.Default); + AppEvents.RoutingsMenuRefreshRequested.Publish(); await Reload(); } } @@ -530,12 +530,12 @@ public class MainWindowViewModel : MyReactiveObject await SysProxyHandler.UpdateSysProxy(_config, false); await Task.Delay(1000); }); - AppEvents.TestServerRequested.OnNext(Unit.Default); + AppEvents.TestServerRequested.Publish(); var showClashUI = _config.IsRunningCore(ECoreType.sing_box); if (showClashUI) { - AppEvents.ProxiesReloadRequested.OnNext(Unit.Default); + AppEvents.ProxiesReloadRequested.Publish(); } RxApp.MainThreadScheduler.Schedule(() => ReloadResult(showClashUI)); @@ -565,7 +565,7 @@ public class MainWindowViewModel : MyReactiveObject { if (_config.UiItem.AutoHideStartup) { - AppEvents.ShowHideWindowRequested.OnNext(false); + AppEvents.ShowHideWindowRequested.Publish(false); } await Task.CompletedTask; } @@ -578,7 +578,7 @@ public class MainWindowViewModel : MyReactiveObject { await ConfigHandler.ApplyRegionalPreset(_config, type); await ConfigHandler.InitRouting(_config); - AppEvents.RoutingsMenuRefreshRequested.OnNext(Unit.Default); + AppEvents.RoutingsMenuRefreshRequested.Publish(); await ConfigHandler.SaveConfig(_config); await new UpdateService().UpdateGeoFileAll(_config, UpdateTaskHandler); diff --git a/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs b/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs index fcf3450d..b36c933c 100644 --- a/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs @@ -275,7 +275,7 @@ public class ProfilesViewModel : MyReactiveObject private void Reload() { - AppEvents.ReloadRequested.OnNext(Unit.Default); + AppEvents.ReloadRequested.Publish(); } public async Task SetSpeedTestResult(SpeedTestResult result) @@ -361,7 +361,7 @@ public class ProfilesViewModel : MyReactiveObject public async Task RefreshServers() { - AppEvents.ProfilesRefreshRequested.OnNext(Unit.Default); + AppEvents.ProfilesRefreshRequested.Publish(); await Task.Delay(200); } diff --git a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs index 6dc795ef..26386e0f 100644 --- a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs @@ -148,17 +148,17 @@ public class StatusBarViewModel : MyReactiveObject NotifyLeftClickCmd = ReactiveCommand.CreateFromTask(async () => { - AppEvents.ShowHideWindowRequested.OnNext(null); + AppEvents.ShowHideWindowRequested.Publish(null); await Task.CompletedTask; }); ShowWindowCmd = ReactiveCommand.CreateFromTask(async () => { - AppEvents.ShowHideWindowRequested.OnNext(true); + AppEvents.ShowHideWindowRequested.Publish(true); await Task.CompletedTask; }); HideWindowCmd = ReactiveCommand.CreateFromTask(async () => { - AppEvents.ShowHideWindowRequested.OnNext(false); + AppEvents.ShowHideWindowRequested.Publish(false); await Task.CompletedTask; }); @@ -274,19 +274,19 @@ public class StatusBarViewModel : MyReactiveObject private async Task AddServerViaClipboard() { - AppEvents.AddServerViaClipboardRequested.OnNext(Unit.Default); + AppEvents.AddServerViaClipboardRequested.Publish(); await Task.Delay(1000); } private async Task AddServerViaScan() { - AppEvents.AddServerViaScanRequested.OnNext(Unit.Default); + AppEvents.AddServerViaScanRequested.Publish(); await Task.Delay(1000); } private async Task UpdateSubscriptionProcess(bool blProxy) { - AppEvents.SubscriptionsUpdateRequested.OnNext(blProxy); + AppEvents.SubscriptionsUpdateRequested.Publish(blProxy); await Task.Delay(1000); } @@ -348,7 +348,7 @@ public class StatusBarViewModel : MyReactiveObject { return; } - AppEvents.SetDefaultServerRequested.OnNext(SelectedServer.ID); + AppEvents.SetDefaultServerRequested.Publish(SelectedServer.ID); } public async Task TestServerAvailability() @@ -449,7 +449,7 @@ public class StatusBarViewModel : MyReactiveObject if (await ConfigHandler.SetDefaultRouting(_config, item) == 0) { NoticeManager.Instance.SendMessageEx(ResUI.TipChangeRouting); - AppEvents.ReloadRequested.OnNext(Unit.Default); + AppEvents.ReloadRequested.Publish(); _updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null); } } @@ -496,7 +496,7 @@ public class StatusBarViewModel : MyReactiveObject } } await ConfigHandler.SaveConfig(_config); - AppEvents.ReloadRequested.OnNext(Unit.Default); + AppEvents.ReloadRequested.Publish(); } private bool AllowEnableTun() diff --git a/v2rayN/v2rayN.Desktop/App.axaml.cs b/v2rayN/v2rayN.Desktop/App.axaml.cs index fa4779cf..a3468a01 100644 --- a/v2rayN/v2rayN.Desktop/App.axaml.cs +++ b/v2rayN/v2rayN.Desktop/App.axaml.cs @@ -54,7 +54,7 @@ public partial class App : Application { if (desktop.MainWindow != null) { - AppEvents.AddServerViaClipboardRequested.OnNext(Unit.Default); + AppEvents.AddServerViaClipboardRequested.Publish(); await Task.Delay(1000); } } diff --git a/v2rayN/v2rayN.Desktop/GlobalUsings.cs b/v2rayN/v2rayN.Desktop/GlobalUsings.cs index 4f2b931d..aede90cc 100644 --- a/v2rayN/v2rayN.Desktop/GlobalUsings.cs +++ b/v2rayN/v2rayN.Desktop/GlobalUsings.cs @@ -2,6 +2,7 @@ global using ServiceLib; global using ServiceLib.Base; global using ServiceLib.Common; global using ServiceLib.Enums; +global using ServiceLib.Events; global using ServiceLib.Handler; global using ServiceLib.Manager; global using ServiceLib.Models; diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs index 86bd5d7b..6c56cefc 100644 --- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs @@ -253,7 +253,7 @@ public partial class MainWindow : WindowBase case EGlobalHotkey.SystemProxySet: case EGlobalHotkey.SystemProxyUnchanged: case EGlobalHotkey.SystemProxyPac: - AppEvents.SysProxyChangeRequested.OnNext((ESysProxyType)((int)e - 1)); + AppEvents.SysProxyChangeRequested.Publish((ESysProxyType)((int)e - 1)); break; } } diff --git a/v2rayN/v2rayN/GlobalUsings.cs b/v2rayN/v2rayN/GlobalUsings.cs index 4f2b931d..aede90cc 100644 --- a/v2rayN/v2rayN/GlobalUsings.cs +++ b/v2rayN/v2rayN/GlobalUsings.cs @@ -2,6 +2,7 @@ global using ServiceLib; global using ServiceLib.Base; global using ServiceLib.Common; global using ServiceLib.Enums; +global using ServiceLib.Events; global using ServiceLib.Handler; global using ServiceLib.Manager; global using ServiceLib.Models; diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml.cs b/v2rayN/v2rayN/Views/MainWindow.xaml.cs index 1d0d530c..39bc3985 100644 --- a/v2rayN/v2rayN/Views/MainWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/MainWindow.xaml.cs @@ -241,7 +241,7 @@ public partial class MainWindow case EGlobalHotkey.SystemProxySet: case EGlobalHotkey.SystemProxyUnchanged: case EGlobalHotkey.SystemProxyPac: - AppEvents.SysProxyChangeRequested.OnNext((ESysProxyType)((int)e - 1)); + AppEvents.SysProxyChangeRequested.Publish((ESysProxyType)((int)e - 1)); break; } }