diff --git a/v2rayN/Directory.Packages.props b/v2rayN/Directory.Packages.props index 5f9a52d0..43266ab7 100644 --- a/v2rayN/Directory.Packages.props +++ b/v2rayN/Directory.Packages.props @@ -12,16 +12,16 @@ - + - - - + + + diff --git a/v2rayN/ServiceLib.Tests/GlobalUsings.cs b/v2rayN/ServiceLib.Tests/GlobalUsings.cs index 9d311324..52bc6321 100644 --- a/v2rayN/ServiceLib.Tests/GlobalUsings.cs +++ b/v2rayN/ServiceLib.Tests/GlobalUsings.cs @@ -3,9 +3,6 @@ global using System.Diagnostics; global using System.Net; global using System.Net.NetworkInformation; global using System.Net.Sockets; -global using System.Reactive; -global using System.Reactive.Disposables; -global using System.Reactive.Linq; global using System.Reflection; global using System.Runtime.InteropServices; global using System.Security.Cryptography; @@ -15,10 +12,7 @@ global using System.Text.Json; global using System.Text.Json.Nodes; global using System.Text.Json.Serialization; global using System.Text.RegularExpressions; -global using DynamicData; -global using DynamicData.Binding; global using ReactiveUI; -global using ReactiveUI.Fody.Helpers; global using ServiceLib.Base; global using ServiceLib.Common; global using ServiceLib.Enums; diff --git a/v2rayN/ServiceLib/Base/BulkObservableCollection.cs b/v2rayN/ServiceLib/Base/BulkObservableCollection.cs new file mode 100644 index 00000000..37e026cd --- /dev/null +++ b/v2rayN/ServiceLib/Base/BulkObservableCollection.cs @@ -0,0 +1,66 @@ +namespace ServiceLib.Base; + +public class BulkObservableCollection : ObservableCollection +{ + private bool _suppressNotification = false; + + protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) + { + if (!_suppressNotification) + { + base.OnCollectionChanged(e); + } + } + + protected override void OnPropertyChanged(PropertyChangedEventArgs e) + { + if (!_suppressNotification) + { + base.OnPropertyChanged(e); + } + } + + public void AddRange(IEnumerable? collection) + { + if (collection == null) + { + return; + } + + _suppressNotification = true; + try + { + foreach (var item in collection) + { + Add(item); + } + } + finally + { + _suppressNotification = false; + OnPropertyChanged(new PropertyChangedEventArgs(nameof(Count))); + OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + } + } + + public bool Replace(T oldItem, T newItem) + { + var index = Items.IndexOf(oldItem); + if (index < 0) + { + return false; + } + + Items[index] = newItem; + + OnPropertyChanged(new PropertyChangedEventArgs("Item[]")); + OnCollectionChanged(new NotifyCollectionChangedEventArgs( + NotifyCollectionChangedAction.Replace, + newItem, + oldItem, + index)); + + return true; + } +} diff --git a/v2rayN/ServiceLib/Events/AppEvents.cs b/v2rayN/ServiceLib/Events/AppEvents.cs index c8ba1064..64a4521b 100644 --- a/v2rayN/ServiceLib/Events/AppEvents.cs +++ b/v2rayN/ServiceLib/Events/AppEvents.cs @@ -2,7 +2,7 @@ namespace ServiceLib.Events; public static class AppEvents { - public static readonly EventChannel AddServerViaClipboardRequested = new(); + public static readonly EventChannel AddServerViaClipboardRequested = new(); public static readonly EventChannel HasUpdateNotified = new(); public static readonly EventChannel DispatcherStatisticsRequested = new(); @@ -10,7 +10,7 @@ public static class AppEvents public static readonly EventChannel SendSnackMsgRequested = new(); public static readonly EventChannel SendMsgViewRequested = new(); - public static readonly EventChannel AppExitRequested = new(); + public static readonly EventChannel AppExitRequested = new(); public static readonly EventChannel ShutdownRequested = new(); public static readonly EventChannel SysProxyChangeRequested = new(); diff --git a/v2rayN/ServiceLib/Events/EventChannel.cs b/v2rayN/ServiceLib/Events/EventChannel.cs index 4ca040c6..4e234fc6 100644 --- a/v2rayN/ServiceLib/Events/EventChannel.cs +++ b/v2rayN/ServiceLib/Events/EventChannel.cs @@ -1,27 +1,37 @@ -using System.Reactive.Subjects; - namespace ServiceLib.Events; public sealed class EventChannel { - private readonly ISubject _subject = Subject.Synchronize(new Subject()); + private readonly Signal _signal = new(); + private readonly Lock _gate = new(); + private readonly IObservable _observable; + public EventChannel() + { + _observable = _signal.Synchronize(_gate); + } public IObservable AsObservable() { - return _subject.AsObservable(); + return _observable; } public void Publish(T value) { - _subject.OnNext(value); + lock (_gate) + { + _signal.OnNext(value); + } } public void Publish() { - if (typeof(T) != typeof(Unit)) + if (typeof(T) != typeof(RxVoid)) { - throw new InvalidOperationException("Publish() without value is only valid for EventChannel."); + throw new InvalidOperationException("Publish() without value is only valid for EventChannel."); + } + lock (_gate) + { + _signal.OnNext((T)(object)RxVoid.Default); } - _subject.OnNext((T)(object)Unit.Default); } } diff --git a/v2rayN/ServiceLib/FodyWeavers.xml b/v2rayN/ServiceLib/FodyWeavers.xml deleted file mode 100644 index 63fc1484..00000000 --- a/v2rayN/ServiceLib/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/v2rayN/ServiceLib/GlobalUsings.cs b/v2rayN/ServiceLib/GlobalUsings.cs index 39e67515..11b75497 100644 --- a/v2rayN/ServiceLib/GlobalUsings.cs +++ b/v2rayN/ServiceLib/GlobalUsings.cs @@ -1,11 +1,15 @@ global using System.Collections.Concurrent; +global using System.Collections.ObjectModel; +global using System.Collections.Specialized; +global using System.ComponentModel; global using System.Diagnostics; global using System.Net; global using System.Net.NetworkInformation; global using System.Net.Sockets; -global using System.Reactive; -global using System.Reactive.Disposables; -global using System.Reactive.Linq; +global using ReactiveUI.Primitives; +global using ReactiveUI.Primitives.Concurrency; +global using ReactiveUI.Primitives.Disposables; +global using ReactiveUI.Primitives.Signals; global using System.Reflection; global using System.Runtime.InteropServices; global using System.Runtime.Versioning; @@ -16,10 +20,8 @@ global using System.Text.Json; global using System.Text.Json.Nodes; global using System.Text.Json.Serialization; global using System.Text.RegularExpressions; -global using DynamicData; -global using DynamicData.Binding; global using ReactiveUI; -global using ReactiveUI.Fody.Helpers; +global using ReactiveUI.SourceGenerators; global using ServiceLib.Base; global using ServiceLib.Common; global using ServiceLib.Enums; @@ -39,3 +41,5 @@ global using ServiceLib.Services; global using ServiceLib.Services.CoreConfig; global using ServiceLib.Services.Statistics; global using SQLite; + + diff --git a/v2rayN/ServiceLib/Manager/ProfileExManager.cs b/v2rayN/ServiceLib/Manager/ProfileExManager.cs index f09e52e0..44baf951 100644 --- a/v2rayN/ServiceLib/Manager/ProfileExManager.cs +++ b/v2rayN/ServiceLib/Manager/ProfileExManager.cs @@ -1,5 +1,3 @@ -//using System.Reactive.Linq; - namespace ServiceLib.Manager; public class ProfileExManager diff --git a/v2rayN/ServiceLib/Models/Dto/CheckUpdateModel.cs b/v2rayN/ServiceLib/Models/Dto/CheckUpdateModel.cs index bb9b6075..3fba51fc 100644 --- a/v2rayN/ServiceLib/Models/Dto/CheckUpdateModel.cs +++ b/v2rayN/ServiceLib/Models/Dto/CheckUpdateModel.cs @@ -1,10 +1,10 @@ namespace ServiceLib.Models.Dto; -public class CheckUpdateModel : ReactiveObject +public partial class CheckUpdateModel : ReactiveObject { public bool? IsSelected { get; set; } public ECoreType? CoreType { get; set; } - [Reactive] public string? Remarks { get; set; } + [Reactive] public partial string? Remarks { get; set; } public string? FileName { get; set; } public bool? IsFinished { get; set; } public bool IsGeoFile { get; set; } diff --git a/v2rayN/ServiceLib/Models/Dto/ClashProxyModel.cs b/v2rayN/ServiceLib/Models/Dto/ClashProxyModel.cs index 5e460d9f..535040d3 100644 --- a/v2rayN/ServiceLib/Models/Dto/ClashProxyModel.cs +++ b/v2rayN/ServiceLib/Models/Dto/ClashProxyModel.cs @@ -1,7 +1,7 @@ namespace ServiceLib.Models.Dto; [Serializable] -public class ClashProxyModel : ReactiveObject +public partial class ClashProxyModel : ReactiveObject { public string? Name { get; set; } @@ -9,9 +9,9 @@ public class ClashProxyModel : ReactiveObject public string? Now { get; set; } - [Reactive] public int Delay { get; set; } + [Reactive] public partial int Delay { get; set; } - [Reactive] public string? DelayName { get; set; } + [Reactive] public partial string? DelayName { get; set; } public bool IsActive { get; set; } } diff --git a/v2rayN/ServiceLib/Models/Dto/ProfileItemModel.cs b/v2rayN/ServiceLib/Models/Dto/ProfileItemModel.cs index 7c8b96df..ade4277c 100644 --- a/v2rayN/ServiceLib/Models/Dto/ProfileItemModel.cs +++ b/v2rayN/ServiceLib/Models/Dto/ProfileItemModel.cs @@ -1,7 +1,7 @@ namespace ServiceLib.Models.Dto; [Serializable] -public class ProfileItemModel : ReactiveObject +public partial class ProfileItemModel : ReactiveObject { public bool IsActive { get; set; } public string IndexId { get; set; } @@ -16,30 +16,30 @@ public class ProfileItemModel : ReactiveObject public int Sort { get; set; } [Reactive] - public int Delay { get; set; } + public partial int Delay { get; set; } public decimal Speed { get; set; } [Reactive] - public string DelayVal { get; set; } + public partial string DelayVal { get; set; } [Reactive] - public string SpeedVal { get; set; } + public partial string SpeedVal { get; set; } [Reactive] - public string IpInfo { get; set; } + public partial string IpInfo { get; set; } [Reactive] - public string TodayUp { get; set; } + public partial string TodayUp { get; set; } [Reactive] - public string TodayDown { get; set; } + public partial string TodayDown { get; set; } [Reactive] - public string TotalUp { get; set; } + public partial string TotalUp { get; set; } [Reactive] - public string TotalDown { get; set; } + public partial string TotalDown { get; set; } public string GetSummary() { diff --git a/v2rayN/ServiceLib/ServiceLib.csproj b/v2rayN/ServiceLib/ServiceLib.csproj index ed764506..d97a1a52 100644 --- a/v2rayN/ServiceLib/ServiceLib.csproj +++ b/v2rayN/ServiceLib/ServiceLib.csproj @@ -10,7 +10,10 @@ true - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/v2rayN/ServiceLib/ViewModels/AddGroupServerViewModel.cs b/v2rayN/ServiceLib/ViewModels/AddGroupServerViewModel.cs index 41aae3ae..e29bc16b 100644 --- a/v2rayN/ServiceLib/ViewModels/AddGroupServerViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/AddGroupServerViewModel.cs @@ -1,45 +1,45 @@ namespace ServiceLib.ViewModels; -public class AddGroupServerViewModel : MyReactiveObject, ICloseable +public partial class AddGroupServerViewModel : MyReactiveObject, ICloseable { public event EventHandler? RequestClose; [Reactive] - public ProfileItem SelectedSource { get; set; } + public partial ProfileItem SelectedSource { get; set; } [Reactive] - public ProfileItem SelectedChild { get; set; } + public partial ProfileItem SelectedChild { get; set; } [Reactive] - public IList SelectedChildren { get; set; } + public partial IList SelectedChildren { get; set; } [Reactive] - public string? CoreType { get; set; } + public partial string? CoreType { get; set; } [Reactive] - public string? PolicyGroupType { get; set; } + public partial string? PolicyGroupType { get; set; } [Reactive] - public SubItem? SelectedSubItem { get; set; } + public partial SubItem? SelectedSubItem { get; set; } [Reactive] - public string? Filter { get; set; } + public partial string? Filter { get; set; } - public IObservableCollection SubItems { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection SubItems { get; } = []; - public IObservableCollection ChildItemsObs { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection ChildItemsObs { get; } = []; - public IObservableCollection AllProfilePreviewItemsObs { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection AllProfilePreviewItemsObs { get; } = []; - public ReactiveCommand AddCmd { get; } - public ReactiveCommand RemoveCmd { get; } + public ReactiveCommand AddCmd { get; } + public ReactiveCommand RemoveCmd { get; } - public ReactiveCommand MoveTopCmd { get; } - public ReactiveCommand MoveUpCmd { get; } - public ReactiveCommand MoveDownCmd { get; } - public ReactiveCommand MoveBottomCmd { get; } + public ReactiveCommand MoveTopCmd { get; } + public ReactiveCommand MoveUpCmd { get; } + public ReactiveCommand MoveDownCmd { get; } + public ReactiveCommand MoveBottomCmd { get; } - public ReactiveCommand SaveCmd { get; } + public ReactiveCommand SaveCmd { get; } public AddGroupServerViewModel(ProfileItem profileItem) { diff --git a/v2rayN/ServiceLib/ViewModels/AddServer2ViewModel.cs b/v2rayN/ServiceLib/ViewModels/AddServer2ViewModel.cs index 14f8769b..b0fdfe1f 100644 --- a/v2rayN/ServiceLib/ViewModels/AddServer2ViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/AddServer2ViewModel.cs @@ -1,20 +1,20 @@ namespace ServiceLib.ViewModels; -public class AddServer2ViewModel : MyReactiveObject, ICloseable +public partial class AddServer2ViewModel : MyReactiveObject, ICloseable { public event EventHandler? RequestClose; - public Interaction BrowseConfigFileInteraction { get; } = new(); + public Interaction BrowseConfigFileInteraction { get; } = new(); [Reactive] - public ProfileItem SelectedSource { get; set; } + public partial ProfileItem SelectedSource { get; set; } [Reactive] - public string? CoreType { get; set; } + public partial string? CoreType { get; set; } - public ReactiveCommand BrowseServerCmd { get; } - public ReactiveCommand EditServerCmd { get; } - public ReactiveCommand SaveServerCmd { get; } + public ReactiveCommand BrowseServerCmd { get; } + public ReactiveCommand EditServerCmd { get; } + public ReactiveCommand SaveServerCmd { get; } public bool IsModified { get; set; } public AddServer2ViewModel(ProfileItem profileItem) @@ -23,7 +23,7 @@ public class AddServer2ViewModel : MyReactiveObject, ICloseable BrowseServerCmd = ReactiveCommand.CreateFromTask(async () => { - var fileName = await BrowseConfigFileInteraction.Handle(Unit.Default); + var fileName = await BrowseConfigFileInteraction.Handle(RxVoid.Default); if (fileName.IsNullOrEmpty()) { return; diff --git a/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs b/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs index 536323a7..3f01261d 100644 --- a/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs @@ -1,131 +1,131 @@ namespace ServiceLib.ViewModels; -public class AddServerViewModel : MyReactiveObject, ICloseable +public partial class AddServerViewModel : MyReactiveObject, ICloseable { public event EventHandler? RequestClose; [Reactive] - public ProfileItem SelectedSource { get; set; } + public partial ProfileItem SelectedSource { get; set; } [Reactive] - public string? CoreType { get; set; } + public partial string? CoreType { get; set; } [Reactive] - public bool AllowInsecure { get; set; } + public partial bool AllowInsecure { get; set; } [Reactive] - public bool MuxEnabled { get; set; } + public partial bool MuxEnabled { get; set; } [Reactive] - public string Cert { get; set; } + public partial string Cert { get; set; } [Reactive] - public string CertTip { get; set; } + public partial string CertTip { get; set; } [Reactive] - public string CertSha { get; set; } + public partial string CertSha { get; set; } [Reactive] - public string SalamanderPass { get; set; } + public partial string SalamanderPass { get; set; } [Reactive] - public int AlterId { get; set; } + public partial int AlterId { get; set; } [Reactive] - public string Ports { get; set; } + public partial string Ports { get; set; } [Reactive] - public int? UpMbps { get; set; } + public partial int? UpMbps { get; set; } [Reactive] - public int? DownMbps { get; set; } + public partial int? DownMbps { get; set; } [Reactive] - public string HopInterval { get; set; } + public partial string HopInterval { get; set; } [Reactive] - public string Flow { get; set; } + public partial string Flow { get; set; } [Reactive] - public string VmessSecurity { get; set; } + public partial string VmessSecurity { get; set; } [Reactive] - public string VlessEncryption { get; set; } + public partial string VlessEncryption { get; set; } [Reactive] - public string SsMethod { get; set; } + public partial string SsMethod { get; set; } [Reactive] - public string WgPublicKey { get; set; } + public partial string WgPublicKey { get; set; } [Reactive] - public string WgPresharedKey { get; set; } + public partial string WgPresharedKey { get; set; } [Reactive] - public string WgInterfaceAddress { get; set; } + public partial string WgInterfaceAddress { get; set; } [Reactive] - public string WgReserved { get; set; } + public partial string WgReserved { get; set; } [Reactive] - public int WgMtu { get; set; } + public partial int WgMtu { get; set; } [Reactive] - public bool Uot { get; set; } + public partial bool Uot { get; set; } [Reactive] - public string CongestionControl { get; set; } + public partial string CongestionControl { get; set; } [Reactive] - public int? InsecureConcurrency { get; set; } + public partial int? InsecureConcurrency { get; set; } [Reactive] - public bool NaiveQuic { get; set; } + public partial bool NaiveQuic { get; set; } [Reactive] - public string HttpHeadersJson { get; set; } + public partial string HttpHeadersJson { get; set; } [Reactive] - public string Hy2RealmUrl { get; set; } + public partial string Hy2RealmUrl { get; set; } [Reactive] - public int GeckoMinPacketSize { get; set; } + public partial int GeckoMinPacketSize { get; set; } [Reactive] - public int GeckoMaxPacketSize { get; set; } + public partial int GeckoMaxPacketSize { get; set; } [Reactive] - public string RawHeaderType { get; set; } + public partial string RawHeaderType { get; set; } [Reactive] - public string Host { get; set; } + public partial string Host { get; set; } [Reactive] - public string Path { get; set; } + public partial string Path { get; set; } [Reactive] - public string XhttpMode { get; set; } + public partial string XhttpMode { get; set; } [Reactive] - public string XhttpExtra { get; set; } + public partial string XhttpExtra { get; set; } [Reactive] - public string GrpcAuthority { get; set; } + public partial string GrpcAuthority { get; set; } [Reactive] - public string GrpcServiceName { get; set; } + public partial string GrpcServiceName { get; set; } [Reactive] - public string GrpcMode { get; set; } + public partial string GrpcMode { get; set; } [Reactive] - public string KcpHeaderType { get; set; } + public partial string KcpHeaderType { get; set; } [Reactive] - public string KcpSeed { get; set; } + public partial string KcpSeed { get; set; } [Reactive] - public int? KcpMtu { get; set; } + public partial int? KcpMtu { get; set; } public string TransportHeaderType { @@ -239,9 +239,9 @@ public class AddServerViewModel : MyReactiveObject, ICloseable } } - public ReactiveCommand FetchCertCmd { get; } - public ReactiveCommand FetchCertChainCmd { get; } - public ReactiveCommand SaveCmd { get; } + public ReactiveCommand FetchCertCmd { get; } + public ReactiveCommand FetchCertChainCmd { get; } + public ReactiveCommand SaveCmd { get; } public AddServerViewModel(ProfileItem profileItem) { diff --git a/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs b/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs index 3b1d544c..f0cc0f5d 100644 --- a/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs @@ -1,19 +1,19 @@ namespace ServiceLib.ViewModels; -public class BackupAndRestoreViewModel : MyReactiveObject +public partial class BackupAndRestoreViewModel : MyReactiveObject { private readonly string _guiConfigs = "guiConfigs"; private static string BackupFileName => $"backup_{DateTime.Now:yyyyMMddHHmmss}.zip"; - public ReactiveCommand RemoteBackupCmd { get; } - public ReactiveCommand RemoteRestoreCmd { get; } - public ReactiveCommand WebDavCheckCmd { get; } + public ReactiveCommand RemoteBackupCmd { get; } + public ReactiveCommand RemoteRestoreCmd { get; } + public ReactiveCommand WebDavCheckCmd { get; } [Reactive] - public WebDavItem SelectedSource { get; set; } + public partial WebDavItem SelectedSource { get; set; } [Reactive] - public string OperationMsg { get; set; } = string.Empty; + public partial string OperationMsg { get; set; } = string.Empty; public BackupAndRestoreViewModel() { diff --git a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs index c8f4efc4..9a2133f4 100644 --- a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs @@ -1,18 +1,18 @@ namespace ServiceLib.ViewModels; -public class CheckUpdateViewModel : MyReactiveObject +public partial class CheckUpdateViewModel : MyReactiveObject { private const string _geo = "GeoFiles"; private readonly ECoreType _v2rayN = ECoreType.v2rayN; private List _lstUpdated = []; private static readonly string _tag = "CheckUpdateViewModel"; - public EventChannel ReloadRequested { get; } = new(); + public EventChannel ReloadRequested { get; } = new(); - public IObservableCollection CheckUpdateModels { get; } = new ObservableCollectionExtended(); - public ReactiveCommand CheckUpdateCmd { get; } - public ReactiveCommand CheckOnlyCmd { get; } - [Reactive] public bool EnableCheckPreReleaseUpdate { get; set; } + public BulkObservableCollection CheckUpdateModels { get; } = []; + public ReactiveCommand CheckUpdateCmd { get; } + public ReactiveCommand CheckOnlyCmd { get; } + [Reactive] public partial bool EnableCheckPreReleaseUpdate { get; set; } public CheckUpdateViewModel() { @@ -288,10 +288,9 @@ public class CheckUpdateViewModel : MyReactiveObject private async Task UpdateFinishedSub(bool blReload) { - RxSchedulers.MainThreadScheduler.Schedule(blReload, (scheduler, blReload) => + RxSchedulers.MainThreadScheduler.Schedule(() => { _ = UpdateFinishedResult(blReload); - return Disposable.Empty; }); await Task.CompletedTask; } @@ -404,10 +403,9 @@ public class CheckUpdateViewModel : MyReactiveObject Remarks = msg, }; - RxSchedulers.MainThreadScheduler.Schedule(item, (scheduler, model) => + RxSchedulers.MainThreadScheduler.Schedule(() => { - _ = UpdateViewResult(model); - return Disposable.Empty; + _ = UpdateViewResult(item); }); await Task.CompletedTask; } diff --git a/v2rayN/ServiceLib/ViewModels/ClashConnectionsViewModel.cs b/v2rayN/ServiceLib/ViewModels/ClashConnectionsViewModel.cs index 384f39c4..053f000a 100644 --- a/v2rayN/ServiceLib/ViewModels/ClashConnectionsViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/ClashConnectionsViewModel.cs @@ -1,20 +1,20 @@ namespace ServiceLib.ViewModels; -public class ClashConnectionsViewModel : MyReactiveObject +public partial class ClashConnectionsViewModel : MyReactiveObject { - public IObservableCollection ConnectionItems { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection ConnectionItems { get; } = []; [Reactive] - public ClashConnectionModel SelectedSource { get; set; } + public partial ClashConnectionModel SelectedSource { get; set; } - public ReactiveCommand ConnectionCloseCmd { get; } - public ReactiveCommand ConnectionCloseAllCmd { get; } + public ReactiveCommand ConnectionCloseCmd { get; } + public ReactiveCommand ConnectionCloseAllCmd { get; } [Reactive] - public string HostFilter { get; set; } + public partial string HostFilter { get; set; } [Reactive] - public bool AutoRefresh { get; set; } + public partial bool AutoRefresh { get; set; } public ClashConnectionsViewModel() { @@ -55,10 +55,9 @@ public class ClashConnectionsViewModel : MyReactiveObject return; } - RxSchedulers.MainThreadScheduler.Schedule(ret?.connections, (scheduler, model) => + RxSchedulers.MainThreadScheduler.Schedule(() => { - _ = RefreshConnections(model); - return Disposable.Empty; + _ = RefreshConnections(ret?.connections); }); } diff --git a/v2rayN/ServiceLib/ViewModels/ClashProxiesViewModel.cs b/v2rayN/ServiceLib/ViewModels/ClashProxiesViewModel.cs index 5b5be60e..7d6b009f 100644 --- a/v2rayN/ServiceLib/ViewModels/ClashProxiesViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/ClashProxiesViewModel.cs @@ -1,37 +1,36 @@ -using System.Reactive.Concurrency; using static ServiceLib.Models.Dto.ClashProviders; using static ServiceLib.Models.Dto.ClashProxies; namespace ServiceLib.ViewModels; -public class ClashProxiesViewModel : MyReactiveObject +public partial class ClashProxiesViewModel : MyReactiveObject { private Dictionary? _proxies; private Dictionary? _providers; private readonly int _delayTimeout = 99999999; - public IObservableCollection ProxyGroups { get; } = new ObservableCollectionExtended(); - public IObservableCollection ProxyDetails { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection ProxyGroups { get; } = []; + public BulkObservableCollection ProxyDetails { get; } = []; [Reactive] - public ClashProxyModel SelectedGroup { get; set; } + public partial ClashProxyModel SelectedGroup { get; set; } [Reactive] - public ClashProxyModel SelectedDetail { get; set; } + public partial ClashProxyModel SelectedDetail { get; set; } - public ReactiveCommand ProxiesReloadCmd { get; } - public ReactiveCommand ProxiesDelayTestCmd { get; } - public ReactiveCommand ProxiesDelayTestPartCmd { get; } - public ReactiveCommand ProxiesSelectActivityCmd { get; } + public ReactiveCommand ProxiesReloadCmd { get; } + public ReactiveCommand ProxiesDelayTestCmd { get; } + public ReactiveCommand ProxiesDelayTestPartCmd { get; } + public ReactiveCommand ProxiesSelectActivityCmd { get; } [Reactive] - public int RuleModeSelected { get; set; } + public partial int RuleModeSelected { get; set; } [Reactive] - public int SortingSelected { get; set; } + public partial int SortingSelected { get; set; } [Reactive] - public bool AutoRefresh { get; set; } + public partial bool AutoRefresh { get; set; } public ClashProxiesViewModel() { @@ -379,10 +378,9 @@ public class ClashProxiesViewModel : MyReactiveObject } var model = new SpeedTestResult() { IndexId = item.Name, Delay = result }; - RxSchedulers.MainThreadScheduler.Schedule(model, (scheduler, model) => + RxSchedulers.MainThreadScheduler.Schedule(() => { _ = ProxiesDelayTestResult(model); - return Disposable.Empty; }); await Task.CompletedTask; }); diff --git a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs index 562e50cf..d7a83967 100644 --- a/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs @@ -1,44 +1,44 @@ namespace ServiceLib.ViewModels; -public class DNSSettingViewModel : MyReactiveObject, ICloseable +public partial class DNSSettingViewModel : MyReactiveObject, ICloseable { public event EventHandler? RequestClose; - [Reactive] public bool UseSystemHosts { get; set; } - [Reactive] public bool AddCommonHosts { get; set; } - [Reactive] public bool FakeIP { get; set; } - [Reactive] public string FakeIPRange { get; set; } - [Reactive] public bool BlockBindingQuery { get; set; } - [Reactive] public string DirectDNS { get; set; } - [Reactive] public string RemoteDNS { get; set; } - [Reactive] public string BootstrapDNS { get; set; } - [Reactive] public string Strategy4Freedom { get; set; } - [Reactive] public string Strategy4Proxy { get; set; } - [Reactive] public string Strategy4ProxyDial { get; set; } - [Reactive] public string Hosts { get; set; } - [Reactive] public string DirectExpectedIPs { get; set; } - [Reactive] public bool ParallelQuery { get; set; } - [Reactive] public bool ServeStale { get; set; } - [Reactive] public bool EnableHappyEyeballs { get; set; } + [Reactive] public partial bool UseSystemHosts { get; set; } + [Reactive] public partial bool AddCommonHosts { get; set; } + [Reactive] public partial bool FakeIP { get; set; } + [Reactive] public partial string FakeIPRange { get; set; } + [Reactive] public partial bool BlockBindingQuery { get; set; } + [Reactive] public partial string DirectDNS { get; set; } + [Reactive] public partial string RemoteDNS { get; set; } + [Reactive] public partial string BootstrapDNS { get; set; } + [Reactive] public partial string Strategy4Freedom { get; set; } + [Reactive] public partial string Strategy4Proxy { get; set; } + [Reactive] public partial string Strategy4ProxyDial { get; set; } + [Reactive] public partial string Hosts { get; set; } + [Reactive] public partial string DirectExpectedIPs { get; set; } + [Reactive] public partial bool ParallelQuery { get; set; } + [Reactive] public partial bool ServeStale { get; set; } + [Reactive] public partial bool EnableHappyEyeballs { get; set; } - [Reactive] public bool UseSystemHostsCompatible { get; set; } - [Reactive] public string DomainStrategy4FreedomCompatible { get; set; } = string.Empty; - [Reactive] public string DomainDNSAddressCompatible { get; set; } = string.Empty; - [Reactive] public string NormalDNSCompatible { get; set; } = string.Empty; - [Reactive] public string TunDNSCompatible { get; set; } = string.Empty; + [Reactive] public partial bool UseSystemHostsCompatible { get; set; } + [Reactive] public partial string DomainStrategy4FreedomCompatible { get; set; } = string.Empty; + [Reactive] public partial string DomainDNSAddressCompatible { get; set; } = string.Empty; + [Reactive] public partial string NormalDNSCompatible { get; set; } = string.Empty; + [Reactive] public partial string TunDNSCompatible { get; set; } = string.Empty; - [Reactive] public string DomainStrategy4Freedom2Compatible { get; set; } = string.Empty; - [Reactive] public string DomainDNSAddress2Compatible { get; set; } = string.Empty; - [Reactive] public string NormalDNS2Compatible { get; set; } = string.Empty; - [Reactive] public string TunDNS2Compatible { get; set; } = string.Empty; - [Reactive] public bool RayCustomDNSEnableCompatible { get; set; } - [Reactive] public bool SBCustomDNSEnableCompatible { get; set; } + [Reactive] public partial string DomainStrategy4Freedom2Compatible { get; set; } = string.Empty; + [Reactive] public partial string DomainDNSAddress2Compatible { get; set; } = string.Empty; + [Reactive] public partial string NormalDNS2Compatible { get; set; } = string.Empty; + [Reactive] public partial string TunDNS2Compatible { get; set; } = string.Empty; + [Reactive] public partial bool RayCustomDNSEnableCompatible { get; set; } + [Reactive] public partial bool SBCustomDNSEnableCompatible { get; set; } - [ObservableAsProperty] public bool IsSimpleDNSEnabled { get; } + public bool IsSimpleDNSEnabled => !(RayCustomDNSEnableCompatible && SBCustomDNSEnableCompatible); - public ReactiveCommand SaveCmd { get; } - public ReactiveCommand ImportDefConfig4V2rayCompatibleCmd { get; } - public ReactiveCommand ImportDefConfig4SingboxCompatibleCmd { get; } + public ReactiveCommand SaveCmd { get; } + public ReactiveCommand ImportDefConfig4V2rayCompatibleCmd { get; } + public ReactiveCommand ImportDefConfig4SingboxCompatibleCmd { get; } public DNSSettingViewModel() { @@ -60,8 +60,7 @@ public class DNSSettingViewModel : MyReactiveObject, ICloseable }); this.WhenAnyValue(x => x.RayCustomDNSEnableCompatible, x => x.SBCustomDNSEnableCompatible) - .Select(x => x is not { Item1: true, Item2: true }) - .ToPropertyEx(this, x => x.IsSimpleDNSEnabled); + .Subscribe(_ => this.RaisePropertyChanged(nameof(IsSimpleDNSEnabled))); _ = Init(); } diff --git a/v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs b/v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs index 8a104e1b..b10c2cf6 100644 --- a/v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs @@ -1,42 +1,42 @@ namespace ServiceLib.ViewModels; -public class FullConfigTemplateViewModel : MyReactiveObject, ICloseable +public partial class FullConfigTemplateViewModel : MyReactiveObject, ICloseable { public event EventHandler? RequestClose; #region Reactive [Reactive] - public bool EnableFullConfigTemplate4Ray { get; set; } + public partial bool EnableFullConfigTemplate4Ray { get; set; } [Reactive] - public bool EnableFullConfigTemplate4Singbox { get; set; } + public partial bool EnableFullConfigTemplate4Singbox { get; set; } [Reactive] - public string FullConfigTemplate4Ray { get; set; } = string.Empty; + public partial string FullConfigTemplate4Ray { get; set; } = string.Empty; [Reactive] - public string FullTunConfigTemplate4Ray { get; set; } = string.Empty; + public partial string FullTunConfigTemplate4Ray { get; set; } = string.Empty; [Reactive] - public string FullConfigTemplate4Singbox { get; set; } = string.Empty; + public partial string FullConfigTemplate4Singbox { get; set; } = string.Empty; [Reactive] - public string FullTunConfigTemplate4Singbox { get; set; } = string.Empty; + public partial string FullTunConfigTemplate4Singbox { get; set; } = string.Empty; [Reactive] - public bool AddProxyOnly4Ray { get; set; } + public partial bool AddProxyOnly4Ray { get; set; } [Reactive] - public bool AddProxyOnly4Singbox { get; set; } + public partial bool AddProxyOnly4Singbox { get; set; } [Reactive] - public string ProxyDetour4Ray { get; set; } = string.Empty; + public partial string ProxyDetour4Ray { get; set; } = string.Empty; [Reactive] - public string ProxyDetour4Singbox { get; set; } = string.Empty; + public partial string ProxyDetour4Singbox { get; set; } = string.Empty; - public ReactiveCommand SaveCmd { get; } + public ReactiveCommand SaveCmd { get; } #endregion Reactive diff --git a/v2rayN/ServiceLib/ViewModels/GlobalHotkeySettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/GlobalHotkeySettingViewModel.cs index 3933aa5b..b630457a 100644 --- a/v2rayN/ServiceLib/ViewModels/GlobalHotkeySettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/GlobalHotkeySettingViewModel.cs @@ -6,7 +6,7 @@ public class GlobalHotkeySettingViewModel : MyReactiveObject, ICloseable private readonly List _globalHotkeys; - public ReactiveCommand SaveCmd { get; } + public ReactiveCommand SaveCmd { get; } public GlobalHotkeySettingViewModel() { diff --git a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs index 611c2cab..171acf13 100644 --- a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs @@ -1,13 +1,11 @@ -using System.Reactive.Concurrency; - namespace ServiceLib.ViewModels; -public class MainWindowViewModel : MyReactiveObject +public partial class MainWindowViewModel : MyReactiveObject { - public Interaction ReadTextFromClipboardInteraction { get; } = new(); - public Interaction ScanScreenInteraction { get; } = new(); - public Interaction BrowseImageFileInteraction { get; } = new(); - public Interaction ShowHideWindowInteraction { get; } = new(); + public Interaction ReadTextFromClipboardInteraction { get; } = new(); + public Interaction ScanScreenInteraction { get; } = new(); + public Interaction BrowseImageFileInteraction { get; } = new(); + public Interaction ShowHideWindowInteraction { get; } = new(); public bool DesignMode { get; set; } @@ -22,67 +20,67 @@ public class MainWindowViewModel : MyReactiveObject #region Menu //servers - public ReactiveCommand AddVmessServerCmd { get; } + public ReactiveCommand AddVmessServerCmd { get; } - public ReactiveCommand AddVlessServerCmd { get; } - public ReactiveCommand AddShadowsocksServerCmd { get; } - public ReactiveCommand AddSocksServerCmd { get; } - public ReactiveCommand AddHttpServerCmd { get; } - public ReactiveCommand AddTrojanServerCmd { get; } - public ReactiveCommand AddHysteria2ServerCmd { get; } - public ReactiveCommand AddTuicServerCmd { get; } - public ReactiveCommand AddWireguardServerCmd { get; } - public ReactiveCommand AddAnytlsServerCmd { get; } - public ReactiveCommand AddNaiveServerCmd { get; } - public ReactiveCommand AddCustomServerCmd { get; } - public ReactiveCommand AddPolicyGroupServerCmd { get; } - public ReactiveCommand AddProxyChainServerCmd { get; } - public ReactiveCommand AddServerViaClipboardCmd { get; } - public ReactiveCommand AddServerViaScanCmd { get; } - public ReactiveCommand AddServerViaImageCmd { get; } + public ReactiveCommand AddVlessServerCmd { get; } + public ReactiveCommand AddShadowsocksServerCmd { get; } + public ReactiveCommand AddSocksServerCmd { get; } + public ReactiveCommand AddHttpServerCmd { get; } + public ReactiveCommand AddTrojanServerCmd { get; } + public ReactiveCommand AddHysteria2ServerCmd { get; } + public ReactiveCommand AddTuicServerCmd { get; } + public ReactiveCommand AddWireguardServerCmd { get; } + public ReactiveCommand AddAnytlsServerCmd { get; } + public ReactiveCommand AddNaiveServerCmd { get; } + public ReactiveCommand AddCustomServerCmd { get; } + public ReactiveCommand AddPolicyGroupServerCmd { get; } + public ReactiveCommand AddProxyChainServerCmd { get; } + public ReactiveCommand AddServerViaClipboardCmd { get; } + public ReactiveCommand AddServerViaScanCmd { get; } + public ReactiveCommand AddServerViaImageCmd { get; } //Subscription - public ReactiveCommand SubSettingCmd { get; } + public ReactiveCommand SubSettingCmd { get; } - public ReactiveCommand SubUpdateCmd { get; } - public ReactiveCommand SubUpdateViaProxyCmd { get; } - public ReactiveCommand SubGroupUpdateCmd { get; } - public ReactiveCommand SubGroupUpdateViaProxyCmd { get; } + public ReactiveCommand SubUpdateCmd { get; } + public ReactiveCommand SubUpdateViaProxyCmd { get; } + public ReactiveCommand SubGroupUpdateCmd { get; } + public ReactiveCommand SubGroupUpdateViaProxyCmd { get; } //Setting - public ReactiveCommand OptionSettingCmd { get; } + public ReactiveCommand OptionSettingCmd { get; } - public ReactiveCommand RoutingSettingCmd { get; } - public ReactiveCommand DNSSettingCmd { get; } - public ReactiveCommand FullConfigTemplateCmd { get; } - public ReactiveCommand GlobalHotkeySettingCmd { get; } - public ReactiveCommand RebootAsAdminCmd { get; } - public ReactiveCommand ClearServerStatisticsCmd { get; } - public ReactiveCommand OpenTheFileLocationCmd { get; } + public ReactiveCommand RoutingSettingCmd { get; } + public ReactiveCommand DNSSettingCmd { get; } + public ReactiveCommand FullConfigTemplateCmd { get; } + public ReactiveCommand GlobalHotkeySettingCmd { get; } + public ReactiveCommand RebootAsAdminCmd { get; } + public ReactiveCommand ClearServerStatisticsCmd { get; } + public ReactiveCommand OpenTheFileLocationCmd { get; } //Presets - public ReactiveCommand RegionalPresetDefaultCmd { get; } + public ReactiveCommand RegionalPresetDefaultCmd { get; } - public ReactiveCommand RegionalPresetRussiaCmd { get; } + public ReactiveCommand RegionalPresetRussiaCmd { get; } - public ReactiveCommand RegionalPresetIranCmd { get; } + public ReactiveCommand RegionalPresetIranCmd { get; } - public ReactiveCommand ReloadCmd { get; } + public ReactiveCommand ReloadCmd { get; } [Reactive] - public bool BlReloadEnabled { get; set; } + public partial bool BlReloadEnabled { get; set; } [Reactive] - public bool ShowClashUI { get; set; } + public partial bool ShowClashUI { get; set; } [Reactive] - public int TabMainSelectedIndex { get; set; } + public partial int TabMainSelectedIndex { get; set; } - [Reactive] public bool BlIsWindows { get; set; } + [Reactive] public partial bool BlIsWindows { get; set; } - [Reactive] public bool BlNewUpdate { get; set; } + [Reactive] public partial bool BlNewUpdate { get; set; } - [Reactive] public EGirdOrientation MainGirdOrientation { get; set; } + [Reactive] public partial EGirdOrientation MainGirdOrientation { get; set; } #endregion Menu @@ -268,7 +266,7 @@ public class MainWindowViewModel : MyReactiveObject .ObserveOn(RxSchedulers.MainThreadScheduler) .Subscribe(async _ => await RefreshServers()); - var vmReloadRequestedList = new List> + var vmReloadRequestedList = new List> { ProfilesViewModel.ReloadRequested.AsObservable(), StatusBarViewModel.ReloadRequested.AsObservable(), @@ -407,12 +405,34 @@ public class MainWindowViewModel : MyReactiveObject private async Task RefreshServersDispatcherAsync() { - await Observable.Start(async () => await RefreshServers(), RxSchedulers.MainThreadScheduler); + //await Observable.Start(async () => await RefreshServers(), RxSchedulers.MainThreadScheduler); + + var uiContext = SynchronizationContext.Current; + if (uiContext != null) + { + var uiSequencer = new SynchronizationContextSequencer(uiContext); + uiSequencer.Schedule(() => _ = RefreshServers()); + } + else + { + await RefreshServers(); + } } private async Task RefreshSubscriptions() { - await Observable.Start(async () => await ProfilesViewModel.RefreshSubscriptions(), RxSchedulers.MainThreadScheduler); + //await Observable.Start(async () => await ProfilesViewModel.RefreshSubscriptions(), RxSchedulers.MainThreadScheduler); + + var uiContext = SynchronizationContext.Current; + if (uiContext != null) + { + var uiSequencer = new SynchronizationContextSequencer(uiContext); + uiSequencer.Schedule(() => _ = ProfilesViewModel.RefreshSubscriptions()); + } + else + { + await ProfilesViewModel.RefreshSubscriptions(); + } } #endregion Servers && Groups @@ -459,7 +479,7 @@ public class MainWindowViewModel : MyReactiveObject var stringData = clipboardData; if (clipboardData == null) { - var result = await ReadTextFromClipboardInteraction.Handle(Unit.Default); + var result = await ReadTextFromClipboardInteraction.Handle(RxVoid.Default); if (result.IsNullOrEmpty()) { NoticeManager.Instance.Enqueue(ResUI.OperationFailed); @@ -482,7 +502,7 @@ public class MainWindowViewModel : MyReactiveObject public async Task AddServerViaScanAsync() { - var result = await ScanScreenInteraction.Handle(Unit.Default); + var result = await ScanScreenInteraction.Handle(RxVoid.Default); await ScanScreenResult(result); } @@ -494,7 +514,7 @@ public class MainWindowViewModel : MyReactiveObject public async Task AddServerViaImageAsync() { - var imageFileName = await BrowseImageFileInteraction.Handle(Unit.Default); + var imageFileName = await BrowseImageFileInteraction.Handle(RxVoid.Default); await AddScanResultAsync(imageFileName); } diff --git a/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs b/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs index 7bc84c30..5dd3c3c8 100644 --- a/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs @@ -1,8 +1,8 @@ namespace ServiceLib.ViewModels; -public class MsgViewModel : MyReactiveObject +public partial class MsgViewModel : MyReactiveObject { - public Interaction DispatcherShowMsgInteraction { get; } = new(); + public Interaction DispatcherShowMsgInteraction { get; } = new(); private readonly ConcurrentQueue _queueMsg = new(); private volatile bool _lastMsgFilterNotAvailable; @@ -10,10 +10,10 @@ public class MsgViewModel : MyReactiveObject public int NumMaxMsg { get; } = 500; [Reactive] - public string MsgFilter { get; set; } + public partial string MsgFilter { get; set; } [Reactive] - public bool AutoRefresh { get; set; } + public partial bool AutoRefresh { get; set; } public MsgViewModel() { @@ -36,6 +36,11 @@ public class MsgViewModel : MyReactiveObject .Subscribe(content => _ = AppendQueueMsg(content)); } + public void FlushQueueMsg() + { + _ = AppendQueueMsg(string.Empty); + } + private async Task AppendQueueMsg(string msg) { if (AutoRefresh == false) @@ -65,7 +70,17 @@ public class MsgViewModel : MyReactiveObject sb.Append(line); } - await DispatcherShowMsgInteraction.Handle(sb.ToString()); + if (sb.Length > 0) + { + try + { + await DispatcherShowMsgInteraction.Handle(sb.ToString()); + } + catch (Exception) + { + _queueMsg.Enqueue(sb.ToString()); + } + } } finally { @@ -75,6 +90,11 @@ public class MsgViewModel : MyReactiveObject private void EnqueueQueueMsg(string msg) { + if (string.IsNullOrEmpty(msg)) + { + return; + } + //filter msg if (MsgFilter.IsNotEmpty() && !_lastMsgFilterNotAvailable) { diff --git a/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs index f4fb464a..9131fc4e 100644 --- a/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs @@ -1,119 +1,119 @@ namespace ServiceLib.ViewModels; -public class OptionSettingViewModel : MyReactiveObject, ICloseable +public partial class OptionSettingViewModel : MyReactiveObject, ICloseable { public event EventHandler? RequestClose; #region Core - [Reactive] public int LocalPort { get; set; } - [Reactive] public bool SecondLocalPortEnabled { get; set; } - [Reactive] public bool UdpEnabled { get; set; } - [Reactive] public bool SniffingEnabled { get; set; } + [Reactive] public partial int LocalPort { get; set; } + [Reactive] public partial bool SecondLocalPortEnabled { get; set; } + [Reactive] public partial bool UdpEnabled { get; set; } + [Reactive] public partial bool SniffingEnabled { get; set; } public IList DestOverride { get; set; } - [Reactive] public bool RouteOnly { get; set; } - [Reactive] public bool AllowLANConn { get; set; } - [Reactive] public bool NewPort4LAN { get; set; } - [Reactive] public string User { get; set; } - [Reactive] public string Pass { get; set; } - [Reactive] public bool LogEnabled { get; set; } - [Reactive] public string Loglevel { get; set; } - [Reactive] public string DefFingerprint { get; set; } - [Reactive] public string DefUserAgent { get; set; } - [Reactive] public string SendThrough { get; set; } - [Reactive] public string BindInterface { get; set; } - [Reactive] public string Mux4SboxProtocol { get; set; } - [Reactive] public bool EnableCacheFile4Sbox { get; set; } - [Reactive] public int? HyUpMbps { get; set; } - [Reactive] public int? HyDownMbps { get; set; } - [Reactive] public bool EnableFragment { get; set; } - [Reactive] public bool EnableFinalFragment { get; set; } - [Reactive] public string FragmentPackets { get; set; } - [Reactive] public string FragmentLengths { get; set; } - [Reactive] public string FragmentDelays { get; set; } - [Reactive] public string FragmentMaxSplit { get; set; } + [Reactive] public partial bool RouteOnly { get; set; } + [Reactive] public partial bool AllowLANConn { get; set; } + [Reactive] public partial bool NewPort4LAN { get; set; } + [Reactive] public partial string User { get; set; } + [Reactive] public partial string Pass { get; set; } + [Reactive] public partial bool LogEnabled { get; set; } + [Reactive] public partial string Loglevel { get; set; } + [Reactive] public partial string DefFingerprint { get; set; } + [Reactive] public partial string DefUserAgent { get; set; } + [Reactive] public partial string SendThrough { get; set; } + [Reactive] public partial string BindInterface { get; set; } + [Reactive] public partial string Mux4SboxProtocol { get; set; } + [Reactive] public partial bool EnableCacheFile4Sbox { get; set; } + [Reactive] public partial int? HyUpMbps { get; set; } + [Reactive] public partial int? HyDownMbps { get; set; } + [Reactive] public partial bool EnableFragment { get; set; } + [Reactive] public partial bool EnableFinalFragment { get; set; } + [Reactive] public partial string FragmentPackets { get; set; } + [Reactive] public partial string FragmentLengths { get; set; } + [Reactive] public partial string FragmentDelays { get; set; } + [Reactive] public partial string FragmentMaxSplit { get; set; } #endregion Core #region UI - [Reactive] public bool AutoRun { get; set; } - [Reactive] public bool EnableStatistics { get; set; } - [Reactive] public bool KeepOlderDedupl { get; set; } - [Reactive] public bool DisplayRealTimeSpeed { get; set; } - [Reactive] public bool EnableAutoAdjustMainLvColWidth { get; set; } - [Reactive] public bool AutoHideStartup { get; set; } - [Reactive] public bool Hide2TrayWhenClose { get; set; } - [Reactive] public bool MacOSShowInDock { get; set; } - [Reactive] public bool EnableDragDropSort { get; set; } - [Reactive] public bool DoubleClick2Activate { get; set; } - [Reactive] public int AutoUpdateInterval { get; set; } - [Reactive] public int TrayMenuServersLimit { get; set; } - [Reactive] public string CurrentFontFamily { get; set; } - [Reactive] public int SpeedTestTimeout { get; set; } - [Reactive] public string SpeedTestUrl { get; set; } - [Reactive] public string SpeedPingTestUrl { get; set; } - [Reactive] public string UdpTestTarget { get; set; } - [Reactive] public int MixedConcurrencyCount { get; set; } - [Reactive] public bool EnableHWA { get; set; } - [Reactive] public string SubConvertUrl { get; set; } - [Reactive] public int MainGirdOrientation { get; set; } - [Reactive] public string GeoFileSourceUrl { get; set; } - [Reactive] public string SrsFileSourceUrl { get; set; } - [Reactive] public string RoutingRulesSourceUrl { get; set; } - [Reactive] public string IPAPIUrl { get; set; } - [Reactive] public string RootCertProvider { get; set; } + [Reactive] public partial bool AutoRun { get; set; } + [Reactive] public partial bool EnableStatistics { get; set; } + [Reactive] public partial bool KeepOlderDedupl { get; set; } + [Reactive] public partial bool DisplayRealTimeSpeed { get; set; } + [Reactive] public partial bool EnableAutoAdjustMainLvColWidth { get; set; } + [Reactive] public partial bool AutoHideStartup { get; set; } + [Reactive] public partial bool Hide2TrayWhenClose { get; set; } + [Reactive] public partial bool MacOSShowInDock { get; set; } + [Reactive] public partial bool EnableDragDropSort { get; set; } + [Reactive] public partial bool DoubleClick2Activate { get; set; } + [Reactive] public partial int AutoUpdateInterval { get; set; } + [Reactive] public partial int TrayMenuServersLimit { get; set; } + [Reactive] public partial string CurrentFontFamily { get; set; } + [Reactive] public partial int SpeedTestTimeout { get; set; } + [Reactive] public partial string SpeedTestUrl { get; set; } + [Reactive] public partial string SpeedPingTestUrl { get; set; } + [Reactive] public partial string UdpTestTarget { get; set; } + [Reactive] public partial int MixedConcurrencyCount { get; set; } + [Reactive] public partial bool EnableHWA { get; set; } + [Reactive] public partial string SubConvertUrl { get; set; } + [Reactive] public partial int MainGirdOrientation { get; set; } + [Reactive] public partial string GeoFileSourceUrl { get; set; } + [Reactive] public partial string SrsFileSourceUrl { get; set; } + [Reactive] public partial string RoutingRulesSourceUrl { get; set; } + [Reactive] public partial string IPAPIUrl { get; set; } + [Reactive] public partial string RootCertProvider { get; set; } #endregion UI #region UI visibility - [Reactive] public bool BlIsWindows { get; set; } - [Reactive] public bool BlIsLinux { get; set; } - [Reactive] public bool BlIsIsMacOS { get; set; } - [Reactive] public bool BlIsNonWindows { get; set; } + [Reactive] public partial bool BlIsWindows { get; set; } + [Reactive] public partial bool BlIsLinux { get; set; } + [Reactive] public partial bool BlIsIsMacOS { get; set; } + [Reactive] public partial bool BlIsNonWindows { get; set; } #endregion UI visibility #region System proxy - [Reactive] public bool NotProxyLocalAddress { get; set; } - [Reactive] public string SystemProxyAdvancedProtocol { get; set; } - [Reactive] public string SystemProxyExceptions { get; set; } - [Reactive] public string CustomSystemProxyPacPath { get; set; } - [Reactive] public string CustomSystemProxyScriptPath { get; set; } + [Reactive] public partial bool NotProxyLocalAddress { get; set; } + [Reactive] public partial string SystemProxyAdvancedProtocol { get; set; } + [Reactive] public partial string SystemProxyExceptions { get; set; } + [Reactive] public partial string CustomSystemProxyPacPath { get; set; } + [Reactive] public partial string CustomSystemProxyScriptPath { get; set; } #endregion System proxy #region Tun mode - [Reactive] public bool TunAutoRoute { get; set; } - [Reactive] public bool TunStrictRoute { get; set; } - [Reactive] public string TunStack { get; set; } - [Reactive] public int TunMtu { get; set; } - [Reactive] public bool TunEnableIPv6Address { get; set; } - [Reactive] public string TunIcmpRouting { get; set; } - [Reactive] public bool TunEnableLegacyProtect { get; set; } - [Reactive] public string TunRouteExcludeAddress { get; set; } - [Reactive] public string TunIPv4Address { get; set; } - [Reactive] public string TunIPv6Address { get; set; } + [Reactive] public partial bool TunAutoRoute { get; set; } + [Reactive] public partial bool TunStrictRoute { get; set; } + [Reactive] public partial string TunStack { get; set; } + [Reactive] public partial int TunMtu { get; set; } + [Reactive] public partial bool TunEnableIPv6Address { get; set; } + [Reactive] public partial string TunIcmpRouting { get; set; } + [Reactive] public partial bool TunEnableLegacyProtect { get; set; } + [Reactive] public partial string TunRouteExcludeAddress { get; set; } + [Reactive] public partial string TunIPv4Address { get; set; } + [Reactive] public partial string TunIPv6Address { get; set; } #endregion Tun mode #region CoreType - [Reactive] public string CoreType1 { get; set; } - [Reactive] public string CoreType2 { get; set; } - [Reactive] public string CoreType3 { get; set; } - [Reactive] public string CoreType4 { get; set; } - [Reactive] public string CoreType5 { get; set; } - [Reactive] public string CoreType6 { get; set; } - [Reactive] public string CoreType7 { get; set; } - [Reactive] public string CoreType9 { get; set; } + [Reactive] public partial string CoreType1 { get; set; } + [Reactive] public partial string CoreType2 { get; set; } + [Reactive] public partial string CoreType3 { get; set; } + [Reactive] public partial string CoreType4 { get; set; } + [Reactive] public partial string CoreType5 { get; set; } + [Reactive] public partial string CoreType6 { get; set; } + [Reactive] public partial string CoreType7 { get; set; } + [Reactive] public partial string CoreType9 { get; set; } #endregion CoreType - public ReactiveCommand SaveCmd { get; } + public ReactiveCommand SaveCmd { get; } public OptionSettingViewModel() { diff --git a/v2rayN/ServiceLib/ViewModels/ProfilesSelectViewModel.cs b/v2rayN/ServiceLib/ViewModels/ProfilesSelectViewModel.cs index 430469e4..761523f2 100644 --- a/v2rayN/ServiceLib/ViewModels/ProfilesSelectViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/ProfilesSelectViewModel.cs @@ -1,10 +1,10 @@ namespace ServiceLib.ViewModels; -public class ProfilesSelectViewModel : MyReactiveObject, ICloseable +public partial class ProfilesSelectViewModel : MyReactiveObject, ICloseable { public event EventHandler? RequestClose; - - public Interaction ProfilesFocusInteraction { get; } = new(); + + public Interaction ProfilesFocusInteraction { get; } = new(); #region private prop @@ -16,34 +16,34 @@ public class ProfilesSelectViewModel : MyReactiveObject, ICloseable #endregion private prop - public ReactiveCommand SaveCmd { get; } + public ReactiveCommand SaveCmd { get; } #region ObservableCollection - public IObservableCollection ProfileItems { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection ProfileItems { get; } = []; - public IObservableCollection SubItems { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection SubItems { get; } = []; [Reactive] - public ProfileItemModel SelectedProfile { get; set; } + public partial ProfileItemModel SelectedProfile { get; set; } public IList SelectedProfiles { get; set; } [Reactive] - public SubItem SelectedSub { get; set; } + public partial SubItem SelectedSub { get; set; } [Reactive] - public string ServerFilter { get; set; } + public partial string ServerFilter { get; set; } // Include/Exclude filter for ConfigType [Reactive] - public List FilterConfigTypes { get; set; } + public partial List FilterConfigTypes { get; set; } [Reactive] - public bool FilterExclude { get; set; } + public partial bool FilterExclude { get; set; } [Reactive] - public bool MultiSelect { get; set; } + public partial bool MultiSelect { get; set; } #endregion ObservableCollection @@ -140,9 +140,9 @@ public class ProfilesSelectViewModel : MyReactiveObject, ICloseable try { - await ProfilesFocusInteraction.Handle(Unit.Default); + await ProfilesFocusInteraction.Handle(RxVoid.Default); } - catch (UnhandledInteractionException) + catch (UnhandledInteractionException) { } } diff --git a/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs b/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs index 1cf2ddc9..6771b22e 100644 --- a/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs @@ -1,17 +1,17 @@ namespace ServiceLib.ViewModels; -public class ProfilesViewModel : MyReactiveObject +public partial class ProfilesViewModel : MyReactiveObject { public Interaction ShowYesNoInteraction { get; } = new(); public Interaction SaveFileDialogInteraction { get; } = new(); - public Interaction SetClipboardDataInteraction { get; } = new(); - public Interaction ProfilesFocusInteraction { get; } = new(); - public Interaction ShareServerInteraction { get; } = new(); - public Interaction DispatcherRefreshServersBizInteraction { get; } = new(); - public Interaction AdjustMainLvColWidthInteraction { get; } = new(); + public Interaction SetClipboardDataInteraction { get; } = new(); + public Interaction ProfilesFocusInteraction { get; } = new(); + public Interaction ShareServerInteraction { get; } = new(); + public Interaction DispatcherRefreshServersBizInteraction { get; } = new(); + public Interaction AdjustMainLvColWidthInteraction { get; } = new(); - public EventChannel ReloadRequested { get; } = new(); - public EventChannel RefreshServersRequested { get; } = new(); + public EventChannel ReloadRequested { get; } = new(); + public EventChannel RefreshServersRequested { get; } = new(); #region private prop @@ -25,69 +25,69 @@ public class ProfilesViewModel : MyReactiveObject #region ObservableCollection - public IObservableCollection ProfileItems { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection ProfileItems { get; } = []; - public IObservableCollection SubItems { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection SubItems { get; } = []; [Reactive] - public ProfileItemModel SelectedProfile { get; set; } + public partial ProfileItemModel SelectedProfile { get; set; } public IList SelectedProfiles { get; set; } [Reactive] - public SubItem SelectedSub { get; set; } + public partial SubItem SelectedSub { get; set; } [Reactive] - public SubItem SelectedMoveToGroup { get; set; } + public partial SubItem SelectedMoveToGroup { get; set; } [Reactive] - public string ServerFilter { get; set; } + public partial string ServerFilter { get; set; } #endregion ObservableCollection #region Menu //servers delete - public ReactiveCommand EditServerCmd { get; } + public ReactiveCommand EditServerCmd { get; } - public ReactiveCommand RemoveServerCmd { get; } - public ReactiveCommand RemoveDuplicateServerCmd { get; } - public ReactiveCommand CopyServerCmd { get; } - public ReactiveCommand SetDefaultServerCmd { get; } - public ReactiveCommand ShareServerCmd { get; } - public ReactiveCommand GenGroupAllServerCmd { get; } - public ReactiveCommand GenGroupRegionServerCmd { get; } + public ReactiveCommand RemoveServerCmd { get; } + public ReactiveCommand RemoveDuplicateServerCmd { get; } + public ReactiveCommand CopyServerCmd { get; } + public ReactiveCommand SetDefaultServerCmd { get; } + public ReactiveCommand ShareServerCmd { get; } + public ReactiveCommand GenGroupAllServerCmd { get; } + public ReactiveCommand GenGroupRegionServerCmd { get; } //servers move - public ReactiveCommand MoveTopCmd { get; } + public ReactiveCommand MoveTopCmd { get; } - public ReactiveCommand MoveUpCmd { get; } - public ReactiveCommand MoveDownCmd { get; } - public ReactiveCommand MoveBottomCmd { get; } - public ReactiveCommand MoveToGroupCmd { get; } + public ReactiveCommand MoveUpCmd { get; } + public ReactiveCommand MoveDownCmd { get; } + public ReactiveCommand MoveBottomCmd { get; } + public ReactiveCommand MoveToGroupCmd { get; } //servers ping - public ReactiveCommand MixedTestServerCmd { get; } + public ReactiveCommand MixedTestServerCmd { get; } - public ReactiveCommand TcpingServerCmd { get; } - public ReactiveCommand RealPingServerCmd { get; } - public ReactiveCommand UdpTestServerCmd { get; } - public ReactiveCommand SpeedServerCmd { get; } - public ReactiveCommand SortServerResultCmd { get; } - public ReactiveCommand RemoveInvalidServerResultCmd { get; } - public ReactiveCommand FastRealPingCmd { get; } + public ReactiveCommand TcpingServerCmd { get; } + public ReactiveCommand RealPingServerCmd { get; } + public ReactiveCommand UdpTestServerCmd { get; } + public ReactiveCommand SpeedServerCmd { get; } + public ReactiveCommand SortServerResultCmd { get; } + public ReactiveCommand RemoveInvalidServerResultCmd { get; } + public ReactiveCommand FastRealPingCmd { get; } //servers export - public ReactiveCommand Export2ClientConfigCmd { get; } + public ReactiveCommand Export2ClientConfigCmd { get; } - public ReactiveCommand Export2ClientConfigClipboardCmd { get; } - public ReactiveCommand Export2ShareUrlCmd { get; } - public ReactiveCommand Export2ShareUrlBase64Cmd { get; } - public ReactiveCommand Export2InnerUriCmd { get; } + public ReactiveCommand Export2ClientConfigClipboardCmd { get; } + public ReactiveCommand Export2ShareUrlCmd { get; } + public ReactiveCommand Export2ShareUrlBase64Cmd { get; } + public ReactiveCommand Export2InnerUriCmd { get; } - public ReactiveCommand AddSubCmd { get; } - public ReactiveCommand EditSubCmd { get; } - public ReactiveCommand DeleteSubCmd { get; } + public ReactiveCommand AddSubCmd { get; } + public ReactiveCommand EditSubCmd { get; } + public ReactiveCommand DeleteSubCmd { get; } #endregion Menu @@ -347,9 +347,9 @@ public class ProfilesViewModel : MyReactiveObject try { - await ProfilesFocusInteraction.Handle(Unit.Default); + await ProfilesFocusInteraction.Handle(RxVoid.Default); } - catch (UnhandledInteractionException) + catch (UnhandledInteractionException) { } } @@ -397,9 +397,9 @@ public class ProfilesViewModel : MyReactiveObject try { - await DispatcherRefreshServersBizInteraction.Handle(Unit.Default); + await DispatcherRefreshServersBizInteraction.Handle(RxVoid.Default); } - catch (UnhandledInteractionException) + catch (UnhandledInteractionException) { } } @@ -419,7 +419,7 @@ public class ProfilesViewModel : MyReactiveObject public async Task AdjustMainLvColWidth() { - await AdjustMainLvColWidthInteraction.Handle(Unit.Default); + await AdjustMainLvColWidthInteraction.Handle(RxVoid.Default); } private async Task?> GetProfileItemsEx(string subid, string filter) @@ -761,10 +761,9 @@ public class ProfilesViewModel : MyReactiveObject _speedtestService ??= new SpeedtestService(_config, async (SpeedTestResult result) => { - RxSchedulers.MainThreadScheduler.Schedule(result, (scheduler, result) => + RxSchedulers.MainThreadScheduler.Schedule(() => { _ = SetSpeedTestResult(result); - return Disposable.Empty; }); await Task.CompletedTask; }); diff --git a/v2rayN/ServiceLib/ViewModels/RoutingRuleDetailsViewModel.cs b/v2rayN/ServiceLib/ViewModels/RoutingRuleDetailsViewModel.cs index 03737c48..593ffc60 100644 --- a/v2rayN/ServiceLib/ViewModels/RoutingRuleDetailsViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/RoutingRuleDetailsViewModel.cs @@ -1,6 +1,6 @@ namespace ServiceLib.ViewModels; -public class RoutingRuleDetailsViewModel : MyReactiveObject, ICloseable +public partial class RoutingRuleDetailsViewModel : MyReactiveObject, ICloseable { public event EventHandler? RequestClose; @@ -8,25 +8,25 @@ public class RoutingRuleDetailsViewModel : MyReactiveObject, ICloseable public IList InboundTagItems { get; set; } [Reactive] - public RulesItem SelectedSource { get; set; } + public partial RulesItem SelectedSource { get; set; } [Reactive] - public string Domain { get; set; } + public partial string Domain { get; set; } [Reactive] - public string IP { get; set; } + public partial string IP { get; set; } [Reactive] - public string Process { get; set; } + public partial string Process { get; set; } [Reactive] - public string? RuleType { get; set; } + public partial string? RuleType { get; set; } [Reactive] - public bool AutoSort { get; set; } + public partial bool AutoSort { get; set; } - public ReactiveCommand SelectProfileCmd { get; } - public ReactiveCommand SaveCmd { get; } + public ReactiveCommand SelectProfileCmd { get; } + public ReactiveCommand SaveCmd { get; } public RoutingRuleDetailsViewModel(RulesItem rulesItem) { diff --git a/v2rayN/ServiceLib/ViewModels/RoutingRuleSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/RoutingRuleSettingViewModel.cs index 1caf0620..48ae8858 100644 --- a/v2rayN/ServiceLib/ViewModels/RoutingRuleSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/RoutingRuleSettingViewModel.cs @@ -1,38 +1,38 @@ namespace ServiceLib.ViewModels; -public class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable +public partial class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable { public event EventHandler? RequestClose; public Interaction ShowYesNoInteraction { get; } = new(); - public Interaction SetClipboardDataInteraction { get; } = new(); - public Interaction ReadTextFromClipboardInteraction { get; } = new(); - public Interaction BrowseRulesFileInteraction { get; } = new(); + public Interaction SetClipboardDataInteraction { get; } = new(); + public Interaction ReadTextFromClipboardInteraction { get; } = new(); + public Interaction BrowseRulesFileInteraction { get; } = new(); private List _rules; [Reactive] - public RoutingItem SelectedRouting { get; set; } + public partial RoutingItem SelectedRouting { get; set; } - public IObservableCollection RulesItems { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection RulesItems { get; } = []; [Reactive] - public RulesItemModel SelectedSource { get; set; } + public partial RulesItemModel SelectedSource { get; set; } public IList SelectedSources { get; set; } - public ReactiveCommand RuleAddCmd { get; } - public ReactiveCommand ImportRulesFromFileCmd { get; } - public ReactiveCommand ImportRulesFromClipboardCmd { get; } - public ReactiveCommand ImportRulesFromUrlCmd { get; } - public ReactiveCommand RuleRemoveCmd { get; } - public ReactiveCommand RuleExportSelectedCmd { get; } - public ReactiveCommand MoveTopCmd { get; } - public ReactiveCommand MoveUpCmd { get; } - public ReactiveCommand MoveDownCmd { get; } - public ReactiveCommand MoveBottomCmd { get; } + public ReactiveCommand RuleAddCmd { get; } + public ReactiveCommand ImportRulesFromFileCmd { get; } + public ReactiveCommand ImportRulesFromClipboardCmd { get; } + public ReactiveCommand ImportRulesFromUrlCmd { get; } + public ReactiveCommand RuleRemoveCmd { get; } + public ReactiveCommand RuleExportSelectedCmd { get; } + public ReactiveCommand MoveTopCmd { get; } + public ReactiveCommand MoveUpCmd { get; } + public ReactiveCommand MoveDownCmd { get; } + public ReactiveCommand MoveBottomCmd { get; } - public ReactiveCommand SaveCmd { get; } + public ReactiveCommand SaveCmd { get; } public RoutingRuleSettingViewModel(RoutingItem routingItem) { @@ -48,7 +48,7 @@ public class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable }); ImportRulesFromFileCmd = ReactiveCommand.CreateFromTask(async () => { - var fileName = await BrowseRulesFileInteraction.Handle(Unit.Default); + var fileName = await BrowseRulesFileInteraction.Handle(RxVoid.Default); await ImportRulesFromFileAsync(fileName); }); ImportRulesFromClipboardCmd = ReactiveCommand.CreateFromTask(async () => @@ -277,7 +277,7 @@ public class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable var stringData = clipboardData; if (clipboardData == null) { - var result = await ReadTextFromClipboardInteraction.Handle(Unit.Default); + var result = await ReadTextFromClipboardInteraction.Handle(RxVoid.Default); if (result.IsNullOrEmpty()) { NoticeManager.Instance.Enqueue(ResUI.OperationFailed); diff --git a/v2rayN/ServiceLib/ViewModels/RoutingSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/RoutingSettingViewModel.cs index 4b248566..d5f26020 100644 --- a/v2rayN/ServiceLib/ViewModels/RoutingSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/RoutingSettingViewModel.cs @@ -1,28 +1,28 @@ namespace ServiceLib.ViewModels; -public class RoutingSettingViewModel : MyReactiveObject +public partial class RoutingSettingViewModel : MyReactiveObject { public Interaction ShowYesNoInteraction { get; } = new(); #region Reactive - public IObservableCollection RoutingItems { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection RoutingItems { get; } = []; [Reactive] - public RoutingItemModel SelectedSource { get; set; } + public partial RoutingItemModel SelectedSource { get; set; } public IList SelectedSources { get; set; } [Reactive] - public string DomainStrategy { get; set; } + public partial string DomainStrategy { get; set; } [Reactive] - public string DomainStrategy4Singbox { get; set; } + public partial string DomainStrategy4Singbox { get; set; } - public ReactiveCommand RoutingAdvancedAddCmd { get; } - public ReactiveCommand RoutingAdvancedRemoveCmd { get; } - public ReactiveCommand RoutingAdvancedSetDefaultCmd { get; } - public ReactiveCommand RoutingAdvancedImportRulesCmd { get; } + public ReactiveCommand RoutingAdvancedAddCmd { get; } + public ReactiveCommand RoutingAdvancedRemoveCmd { get; } + public ReactiveCommand RoutingAdvancedSetDefaultCmd { get; } + public ReactiveCommand RoutingAdvancedImportRulesCmd { get; } public bool IsModified { get; set; } diff --git a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs index 8de4189c..ef675b05 100644 --- a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs @@ -1,10 +1,10 @@ namespace ServiceLib.ViewModels; -public class StatusBarViewModel : MyReactiveObject +public partial class StatusBarViewModel : MyReactiveObject { - public Interaction SetClipboardDataInteraction { get; } = new(); - public Interaction PasswordInputInteraction { get; } = new(); - public Interaction DispatcherRefreshIconInteraction { get; } = new(); + public Interaction SetClipboardDataInteraction { get; } = new(); + public Interaction PasswordInputInteraction { get; } = new(); + public Interaction DispatcherRefreshIconInteraction { get; } = new(); public EventChannel SubscriptionsUpdateRequested { get; } = new(); public EventChannel ShowHideWindowRequested { get; } = new(); @@ -12,94 +12,94 @@ public class StatusBarViewModel : MyReactiveObject public static StatusBarViewModel Instance => _instance.Value; public EventChannel SetDefaultServerRequested { get; } = new(); - public EventChannel ReloadRequested { get; } = new(); - public EventChannel AddServerViaScanRequested { get; } = new(); - public EventChannel AddServerViaClipboardRequested { get; } = new(); + public EventChannel ReloadRequested { get; } = new(); + public EventChannel AddServerViaScanRequested { get; } = new(); + public EventChannel AddServerViaClipboardRequested { get; } = new(); #region ObservableCollection - public IObservableCollection RoutingItems { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection RoutingItems { get; } = []; - public IObservableCollection Servers { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection Servers { get; } = []; [Reactive] - public RoutingItem SelectedRouting { get; set; } + public partial RoutingItem SelectedRouting { get; set; } [Reactive] - public ComboItem SelectedServer { get; set; } + public partial ComboItem SelectedServer { get; set; } [Reactive] - public bool BlServers { get; set; } + public partial bool BlServers { get; set; } #endregion ObservableCollection - public ReactiveCommand AddServerViaClipboardCmd { get; } - public ReactiveCommand AddServerViaScanCmd { get; } - public ReactiveCommand SubUpdateCmd { get; } - public ReactiveCommand SubUpdateViaProxyCmd { get; } - public ReactiveCommand CopyProxyCmdToClipboardCmd { get; } - public ReactiveCommand NotifyLeftClickCmd { get; } - public ReactiveCommand ShowWindowCmd { get; } - public ReactiveCommand HideWindowCmd { get; } + public ReactiveCommand AddServerViaClipboardCmd { get; } + public ReactiveCommand AddServerViaScanCmd { get; } + public ReactiveCommand SubUpdateCmd { get; } + public ReactiveCommand SubUpdateViaProxyCmd { get; } + public ReactiveCommand CopyProxyCmdToClipboardCmd { get; } + public ReactiveCommand NotifyLeftClickCmd { get; } + public ReactiveCommand ShowWindowCmd { get; } + public ReactiveCommand HideWindowCmd { get; } #region System Proxy [Reactive] - public bool BlSystemProxyClear { get; set; } + public partial bool BlSystemProxyClear { get; set; } [Reactive] - public bool BlSystemProxySet { get; set; } + public partial bool BlSystemProxySet { get; set; } [Reactive] - public bool BlSystemProxyNothing { get; set; } + public partial bool BlSystemProxyNothing { get; set; } [Reactive] - public bool BlSystemProxyPac { get; set; } + public partial bool BlSystemProxyPac { get; set; } - public ReactiveCommand SystemProxyClearCmd { get; } - public ReactiveCommand SystemProxySetCmd { get; } - public ReactiveCommand SystemProxyNothingCmd { get; } - public ReactiveCommand SystemProxyPacCmd { get; } + public ReactiveCommand SystemProxyClearCmd { get; } + public ReactiveCommand SystemProxySetCmd { get; } + public ReactiveCommand SystemProxyNothingCmd { get; } + public ReactiveCommand SystemProxyPacCmd { get; } [Reactive] - public bool BlRouting { get; set; } + public partial bool BlRouting { get; set; } [Reactive] - public int SystemProxySelected { get; set; } + public partial int SystemProxySelected { get; set; } [Reactive] - public bool BlSystemProxyPacVisible { get; set; } + public partial bool BlSystemProxyPacVisible { get; set; } #endregion System Proxy #region UI [Reactive] - public string InboundDisplay { get; set; } + public partial string InboundDisplay { get; set; } [Reactive] - public string InboundLanDisplay { get; set; } + public partial string InboundLanDisplay { get; set; } [Reactive] - public string RunningServerDisplay { get; set; } + public partial string RunningServerDisplay { get; set; } [Reactive] - public string RunningServerToolTipText { get; set; } + public partial string RunningServerToolTipText { get; set; } [Reactive] - public string RunningInfoDisplay { get; set; } + public partial string RunningInfoDisplay { get; set; } [Reactive] - public string SpeedProxyDisplay { get; set; } + public partial string SpeedProxyDisplay { get; set; } [Reactive] - public string SpeedDirectDisplay { get; set; } + public partial string SpeedDirectDisplay { get; set; } [Reactive] - public bool EnableTun { get; set; } + public partial bool EnableTun { get; set; } [Reactive] - public bool BlIsNonWindows { get; set; } + public partial bool BlIsNonWindows { get; set; } #endregion UI @@ -349,10 +349,9 @@ public class StatusBarViewModel : MyReactiveObject private async Task TestServerAvailabilitySub(string msg) { - RxSchedulers.MainThreadScheduler.Schedule(msg, (scheduler, msg) => + RxSchedulers.MainThreadScheduler.Schedule(() => { _ = TestServerAvailabilityResult(msg); - return Disposable.Empty; }); await Task.CompletedTask; } @@ -392,9 +391,9 @@ public class StatusBarViewModel : MyReactiveObject { try { - await DispatcherRefreshIconInteraction.Handle(Unit.Default); + await DispatcherRefreshIconInteraction.Handle(RxVoid.Default); } - catch (UnhandledInteractionException) + catch (UnhandledInteractionException) { // Ignore } @@ -433,7 +432,7 @@ public class StatusBarViewModel : MyReactiveObject { NoticeManager.Instance.SendMessageEx(ResUI.TipChangeRouting); ReloadRequested.Publish(); - await DispatcherRefreshIconInteraction.Handle(Unit.Default); + await DispatcherRefreshIconInteraction.Handle(RxVoid.Default); } } @@ -470,7 +469,7 @@ public class StatusBarViewModel : MyReactiveObject } else { - var password = await PasswordInputInteraction.Handle(Unit.Default); + var password = await PasswordInputInteraction.Handle(RxVoid.Default); if (password.IsNullOrEmpty()) { _config.TunModeItem.EnableTun = false; diff --git a/v2rayN/ServiceLib/ViewModels/SubEditViewModel.cs b/v2rayN/ServiceLib/ViewModels/SubEditViewModel.cs index 3b91cf76..610f6082 100644 --- a/v2rayN/ServiceLib/ViewModels/SubEditViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/SubEditViewModel.cs @@ -1,15 +1,15 @@ namespace ServiceLib.ViewModels; -public class SubEditViewModel : MyReactiveObject, ICloseable +public partial class SubEditViewModel : MyReactiveObject, ICloseable { public event EventHandler? RequestClose; [Reactive] - public SubItem SelectedSource { get; set; } + public partial SubItem SelectedSource { get; set; } - public ReactiveCommand SelectPrevProfileCmd { get; } - public ReactiveCommand SelectNextProfileCmd { get; } - public ReactiveCommand SaveCmd { get; } + public ReactiveCommand SelectPrevProfileCmd { get; } + public ReactiveCommand SelectNextProfileCmd { get; } + public ReactiveCommand SaveCmd { get; } public SubEditViewModel(SubItem subItem) { diff --git a/v2rayN/ServiceLib/ViewModels/SubSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/SubSettingViewModel.cs index e9d1fe59..5c3ef56d 100644 --- a/v2rayN/ServiceLib/ViewModels/SubSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/SubSettingViewModel.cs @@ -1,21 +1,21 @@ namespace ServiceLib.ViewModels; -public class SubSettingViewModel : MyReactiveObject +public partial class SubSettingViewModel : MyReactiveObject { public Interaction ShowYesNoInteraction { get; } = new(); - public Interaction ShareSubInteraction { get; } = new(); + public Interaction ShareSubInteraction { get; } = new(); - public IObservableCollection SubItems { get; } = new ObservableCollectionExtended(); + public BulkObservableCollection SubItems { get; } = []; [Reactive] - public SubItem SelectedSource { get; set; } + public partial SubItem SelectedSource { get; set; } public IList SelectedSources { get; set; } - public ReactiveCommand SubAddCmd { get; } - public ReactiveCommand SubDeleteCmd { get; } - public ReactiveCommand SubEditCmd { get; } - public ReactiveCommand SubShareCmd { get; } + public ReactiveCommand SubAddCmd { get; } + public ReactiveCommand SubDeleteCmd { get; } + public ReactiveCommand SubEditCmd { get; } + public ReactiveCommand SubShareCmd { get; } public bool IsModified { get; set; } public SubSettingViewModel() diff --git a/v2rayN/v2rayN.Desktop/FodyWeavers.xml b/v2rayN/v2rayN.Desktop/FodyWeavers.xml deleted file mode 100644 index 63fc1484..00000000 --- a/v2rayN/v2rayN.Desktop/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/v2rayN/v2rayN.Desktop/GlobalUsings.cs b/v2rayN/v2rayN.Desktop/GlobalUsings.cs index 53b79a33..95fbd967 100644 --- a/v2rayN/v2rayN.Desktop/GlobalUsings.cs +++ b/v2rayN/v2rayN.Desktop/GlobalUsings.cs @@ -3,9 +3,6 @@ global using System.Collections.Generic; global using System.Globalization; global using System.IO; global using System.Linq; -global using System.Reactive; -global using System.Reactive.Disposables.Fluent; -global using System.Reactive.Linq; global using System.Runtime.Versioning; global using System.Text; global using System.Threading; @@ -21,10 +18,11 @@ global using Avalonia.Media.Imaging; global using Avalonia.Platform; global using Avalonia.Styling; global using Avalonia.Threading; -global using DynamicData; global using ReactiveUI; global using ReactiveUI.Avalonia; -global using ReactiveUI.Fody.Helpers; +global using ReactiveUI.Primitives; +global using ReactiveUI.Primitives.Disposables; +global using ReactiveUI.SourceGenerators; global using ServiceLib; global using ServiceLib.Base; global using ServiceLib.Common; diff --git a/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs b/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs index 27a13dda..8728cfbe 100644 --- a/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs +++ b/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs @@ -5,13 +5,13 @@ using Semi.Avalonia; namespace v2rayN.Desktop.ViewModels; -public class ThemeSettingViewModel : MyReactiveObject +public partial class ThemeSettingViewModel : MyReactiveObject { - [Reactive] public string CurrentTheme { get; set; } + [Reactive] public partial string CurrentTheme { get; set; } - [Reactive] public int CurrentFontSize { get; set; } + [Reactive] public partial int CurrentFontSize { get; set; } - [Reactive] public string CurrentLanguage { get; set; } + [Reactive] public partial string CurrentLanguage { get; set; } public ThemeSettingViewModel() { diff --git a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs index 8a828cfa..fa8ccb7d 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs @@ -27,7 +27,7 @@ public partial class AddGroupServerWindow : WindowBase this.WhenActivated(disposables => { this.WhenAnyValue(v => v.ViewModel.SelectedSource) - .WhereNotNull() + .KeepNotNull() .Subscribe(InitializeData) .DisposeWith(disposables); diff --git a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs index 58c58479..a1d5b22d 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs @@ -1,4 +1,3 @@ -using System.Reactive.Disposables; using v2rayN.Desktop.Base; using v2rayN.Desktop.Common; @@ -39,11 +38,12 @@ public partial class AddServerWindow : WindowBase this.WhenActivated(disposables => { this.WhenAnyValue(v => v.ViewModel.SelectedSource) - .WhereNotNull() + .KeepNotNull() .Subscribe(InitializeData) .DisposeWith(disposables); - var configTypeBindings = new SerialDisposable().DisposeWith(disposables); + var configTypeBindings = new SingleReplaceableDisposable(); + configTypeBindings.DisposeWith(disposables); this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables); @@ -53,8 +53,8 @@ public partial class AddServerWindow : WindowBase this.WhenAnyValue(v => v.ViewModel.SelectedSource.ConfigType) .Subscribe(configType => { - var currentTypeDisposables = new CompositeDisposable(); - configTypeBindings.Disposable = currentTypeDisposables; + var currentTypeDisposables = new MultipleDisposable(); + configTypeBindings.Create(currentTypeDisposables); switch (configType) { diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs index 99131d79..1013e07b 100644 --- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs @@ -1,4 +1,3 @@ -using System.Reactive.Disposables; using Avalonia.Controls.Notifications; using DialogHostAvalonia; using v2rayN.Desktop.Base; @@ -10,7 +9,7 @@ namespace v2rayN.Desktop.Views; public partial class MainWindow : WindowBase { private static Config _config; - private readonly SerialDisposable _layoutBindingsDisposable = new(); + private readonly SingleReplaceableDisposable _layoutBindingsDisposable = new(); private readonly WindowNotificationManager? _manager; private CheckUpdateView? _checkUpdateView; private BackupAndRestoreView? _backupAndRestoreView; @@ -111,7 +110,7 @@ public partial class MainWindow : WindowBase ViewModel.ShowHideWindowInteraction.RegisterHandler(interaction => { ShowHideWindow(interaction.Input); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); AppEvents.SendSnackMsgRequested @@ -402,8 +401,8 @@ public partial class MainWindow : WindowBase private void UpdateLayout(EGirdOrientation orientation) { - var currentLayoutDisposables = new CompositeDisposable(); - _layoutBindingsDisposable.Disposable = currentLayoutDisposables; + var currentLayoutDisposables = new MultipleDisposable(); + _layoutBindingsDisposable.Create(currentLayoutDisposables); gridMain.IsVisible = orientation == EGirdOrientation.Horizontal; gridMain1.IsVisible = orientation == EGirdOrientation.Vertical; diff --git a/v2rayN/v2rayN.Desktop/Views/MsgView.axaml.cs b/v2rayN/v2rayN.Desktop/Views/MsgView.axaml.cs index 591cbc14..76ae59d0 100644 --- a/v2rayN/v2rayN.Desktop/Views/MsgView.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/MsgView.axaml.cs @@ -21,8 +21,10 @@ public partial class MsgView : ReactiveUserControl var msg = interaction.Input; Dispatcher.UIThread.Post(() => ShowMsg(msg), DispatcherPriority.ApplicationIdle); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); + + ViewModel?.FlushQueueMsg(); }); TextEditorKeywordHighlighter.Attach(txtMsg, Global.LogLevelColors.ToDictionary( diff --git a/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs index 72efd4dc..9945d63c 100644 --- a/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs @@ -109,8 +109,7 @@ public partial class OptionSettingWindow : WindowBase this.Bind(ViewModel, vm => vm.UdpTestTarget, v => v.cmbUdpTestTarget.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.MixedConcurrencyCount, v => v.cmbMixedConcurrencyCount.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables); - this.Bind(ViewModel, - vm => vm.MainGirdOrientation, view => view.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.MainGirdOrientation, view => view.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.Text).DisposeWith(disposables); diff --git a/v2rayN/v2rayN.Desktop/Views/ProfilesSelectWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/ProfilesSelectWindow.axaml.cs index 6501bc41..6a165d37 100644 --- a/v2rayN/v2rayN.Desktop/Views/ProfilesSelectWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/ProfilesSelectWindow.axaml.cs @@ -35,7 +35,7 @@ public partial class ProfilesSelectWindow : WindowBase ViewModel.ProfilesFocusInteraction.RegisterHandler(interaction => { lstProfiles.Focus(); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); }); } diff --git a/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs b/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs index 7316fbdb..f615eb39 100644 --- a/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs @@ -1,6 +1,5 @@ using Avalonia.VisualTree; using DialogHostAvalonia; -using DynamicData.Binding; using v2rayN.Desktop.Common; namespace v2rayN.Desktop.Views; @@ -113,13 +112,13 @@ public partial class ProfilesView : ReactiveUserControl { var strData = interaction.Input; await AvaUtils.SetClipboardData(this, strData); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.ProfilesFocusInteraction.RegisterHandler(interaction => { lstProfiles.Focus(); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.ShareServerInteraction.RegisterHandler(async interaction => @@ -127,23 +126,23 @@ public partial class ProfilesView : ReactiveUserControl var url = interaction.Input; if (url.IsNullOrEmpty()) { - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); return; } await ShareServer(url); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.DispatcherRefreshServersBizInteraction.RegisterHandler(interaction => { Dispatcher.UIThread.Post(RefreshServersBiz, DispatcherPriority.Default); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.AdjustMainLvColWidthInteraction.RegisterHandler(interaction => { //AutofitColumnWidth(); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); AppEvents.AppExitRequested diff --git a/v2rayN/v2rayN.Desktop/Views/RoutingRuleDetailsWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/RoutingRuleDetailsWindow.axaml.cs index 7124e561..bbd3eae2 100644 --- a/v2rayN/v2rayN.Desktop/Views/RoutingRuleDetailsWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/RoutingRuleDetailsWindow.axaml.cs @@ -22,7 +22,7 @@ public partial class RoutingRuleDetailsWindow : WindowBase { this.WhenAnyValue(v => v.ViewModel.SelectedSource) - .WhereNotNull() + .KeepNotNull() .Subscribe(InitializeData) .DisposeWith(disposables); diff --git a/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml.cs index 20808967..f381b8d8 100644 --- a/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml.cs @@ -61,7 +61,7 @@ public partial class RoutingRuleSettingWindow : WindowBase diff --git a/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs b/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs index 37e42a30..67ad4cfc 100644 --- a/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs @@ -34,7 +34,7 @@ public partial class StatusBarView : ReactiveUserControl { var strData = interaction.Input; await AvaUtils.SetClipboardData(this, strData); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.PasswordInputInteraction.RegisterHandler(async interaction => @@ -46,7 +46,7 @@ public partial class StatusBarView : ReactiveUserControl ViewModel.DispatcherRefreshIconInteraction.RegisterHandler(interaction => { Dispatcher.UIThread.Post(RefreshIcon, DispatcherPriority.Default); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); }); diff --git a/v2rayN/v2rayN.Desktop/Views/SubSettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/SubSettingWindow.axaml.cs index 9279812f..01cfe76b 100644 --- a/v2rayN/v2rayN.Desktop/Views/SubSettingWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/SubSettingWindow.axaml.cs @@ -46,11 +46,11 @@ public partial class SubSettingWindow : WindowBase var url = interaction.Input; if (url.IsNullOrEmpty()) { - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); return; } await ShareSub(url); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); }); } diff --git a/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj b/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj index 753dbc35..345c400a 100644 --- a/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj +++ b/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj @@ -19,6 +19,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -27,9 +31,6 @@ true - - true - diff --git a/v2rayN/v2rayN/Common/SimpleViewLocator.cs b/v2rayN/v2rayN/Common/SimpleViewLocator.cs index e296fd32..b3395fda 100644 --- a/v2rayN/v2rayN/Common/SimpleViewLocator.cs +++ b/v2rayN/v2rayN/Common/SimpleViewLocator.cs @@ -36,7 +36,12 @@ public class SimpleViewLocator : IViewLocator public static SimpleViewLocator Instance => _instance.Value; - public IViewFor? ResolveView(string? contract = null) where TViewModel : class + public IViewFor? ResolveView() where TViewModel : class + { + return ResolveView(null); + } + + public IViewFor? ResolveView(string? contract) where TViewModel : class { if (_mappings.TryGetValue(typeof(TViewModel), out var factory)) { @@ -45,7 +50,12 @@ public class SimpleViewLocator : IViewLocator return null; } - public IViewFor? ResolveView(object? instance, string? contract = null) + public IViewFor? ResolveView(object? instance) + { + return ResolveView(instance, null); + } + + public IViewFor? ResolveView(object? instance, string? contract) { if (instance == null) { diff --git a/v2rayN/v2rayN/FodyWeavers.xml b/v2rayN/v2rayN/FodyWeavers.xml deleted file mode 100644 index 63fc1484..00000000 --- a/v2rayN/v2rayN/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/v2rayN/v2rayN/GlobalUsings.cs b/v2rayN/v2rayN/GlobalUsings.cs index d974109a..2948b5fa 100644 --- a/v2rayN/v2rayN/GlobalUsings.cs +++ b/v2rayN/v2rayN/GlobalUsings.cs @@ -6,9 +6,6 @@ global using System.Diagnostics; global using System.Globalization; global using System.IO; global using System.Linq; -global using System.Reactive; -global using System.Reactive.Disposables.Fluent; -global using System.Reactive.Linq; global using System.Runtime.InteropServices; global using System.Text; global using System.Threading; @@ -18,11 +15,11 @@ global using System.Windows.Data; global using System.Windows.Input; global using System.Windows.Interop; global using System.Windows.Threading; -global using DynamicData; -global using DynamicData.Binding; global using ReactiveUI; global using ReactiveUI.Builder; -global using ReactiveUI.Fody.Helpers; +global using ReactiveUI.Primitives; +global using ReactiveUI.Primitives.Disposables; +global using ReactiveUI.SourceGenerators; global using ServiceLib; global using ServiceLib.Base; global using ServiceLib.Common; diff --git a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs index a84788e2..125ccf31 100644 --- a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs @@ -5,21 +5,20 @@ using Microsoft.Win32; namespace v2rayN.ViewModels; -public class ThemeSettingViewModel : MyReactiveObject +public partial class ThemeSettingViewModel : MyReactiveObject { private readonly PaletteHelper _paletteHelper = new(); - private IObservableCollection _swatches = new ObservableCollectionExtended(); - public IObservableCollection Swatches => _swatches; + public BulkObservableCollection Swatches { get; } = []; [Reactive] - public Swatch SelectedSwatch { get; set; } + public partial Swatch SelectedSwatch { get; set; } - [Reactive] public string CurrentTheme { get; set; } + [Reactive] public partial string CurrentTheme { get; set; } - [Reactive] public int CurrentFontSize { get; set; } + [Reactive] public partial int CurrentFontSize { get; set; } - [Reactive] public string CurrentLanguage { get; set; } + [Reactive] public partial string CurrentLanguage { get; set; } public ThemeSettingViewModel() { @@ -47,10 +46,10 @@ public class ThemeSettingViewModel : MyReactiveObject private void BindingUI() { - _swatches.AddRange(new SwatchesProvider().Swatches); + Swatches.AddRange(new SwatchesProvider().Swatches); if (!_config.UiItem.ColorPrimaryName.IsNullOrEmpty()) { - SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.UiItem.ColorPrimaryName); + SelectedSwatch = Swatches.FirstOrDefault(t => t.Name == _config.UiItem.ColorPrimaryName); } CurrentTheme = _config.UiItem.CurrentTheme; CurrentFontSize = _config.UiItem.CurrentFontSize; diff --git a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs index 0c01660e..02cdab03 100644 --- a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs @@ -26,7 +26,7 @@ public partial class AddGroupServerWindow this.WhenActivated(disposables => { this.WhenAnyValue(v => v.ViewModel.SelectedSource) - .WhereNotNull() + .KeepNotNull() .Subscribe(InitializeData) .DisposeWith(disposables); diff --git a/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs b/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs index d958437a..8ae659c0 100644 --- a/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs @@ -1,4 +1,3 @@ -using System.Reactive.Disposables; using System.Windows.Controls; namespace v2rayN.Views; @@ -37,11 +36,12 @@ public partial class AddServerWindow this.WhenActivated(disposables => { this.WhenAnyValue(v => v.ViewModel.SelectedSource) - .WhereNotNull() + .KeepNotNull() .Subscribe(InitializeData) .DisposeWith(disposables); - var configTypeBindings = new SerialDisposable().DisposeWith(disposables); + var configTypeBindings = new SingleReplaceableDisposable(); + configTypeBindings.DisposeWith(disposables); this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables); @@ -51,8 +51,8 @@ public partial class AddServerWindow this.WhenAnyValue(v => v.ViewModel.SelectedSource.ConfigType) .Subscribe(configType => { - var currentTypeDisposables = new CompositeDisposable(); - configTypeBindings.Disposable = currentTypeDisposables; + var currentTypeDisposables = new MultipleDisposable(); + configTypeBindings.Create(currentTypeDisposables); switch (configType) { diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml.cs b/v2rayN/v2rayN/Views/MainWindow.xaml.cs index d26283ef..cb95657a 100644 --- a/v2rayN/v2rayN/Views/MainWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/MainWindow.xaml.cs @@ -1,4 +1,3 @@ -using System.Reactive.Disposables; using System.Windows.Controls; using System.Windows.Media; using MaterialDesignThemes.Wpf; @@ -10,7 +9,7 @@ namespace v2rayN.Views; public partial class MainWindow { private static Config _config; - private readonly SerialDisposable _layoutBindingsDisposable = new(); + private readonly SingleReplaceableDisposable _layoutBindingsDisposable = new(); private CheckUpdateView? _checkUpdateView; private BackupAndRestoreView? _backupAndRestoreView; @@ -120,7 +119,7 @@ public partial class MainWindow ViewModel.ShowHideWindowInteraction.RegisterHandler(interaction => { ShowHideWindow(interaction.Input); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); AppEvents.SendSnackMsgRequested @@ -358,8 +357,8 @@ public partial class MainWindow private void UpdateLayout(EGirdOrientation orientation) { - var currentLayoutDisposables = new CompositeDisposable(); - _layoutBindingsDisposable.Disposable = currentLayoutDisposables; + var currentLayoutDisposables = new MultipleDisposable(); + _layoutBindingsDisposable.Create(currentLayoutDisposables); gridMain.Visibility = orientation == EGirdOrientation.Horizontal ? Visibility.Visible : Visibility.Collapsed; gridMain1.Visibility = orientation == EGirdOrientation.Vertical ? Visibility.Visible : Visibility.Collapsed; diff --git a/v2rayN/v2rayN/Views/MsgView.xaml.cs b/v2rayN/v2rayN/Views/MsgView.xaml.cs index 78309fdc..b05f8cd0 100644 --- a/v2rayN/v2rayN/Views/MsgView.xaml.cs +++ b/v2rayN/v2rayN/Views/MsgView.xaml.cs @@ -18,8 +18,10 @@ public partial class MsgView { ShowMsg(msg); }, DispatcherPriority.ApplicationIdle); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); + + ViewModel?.FlushQueueMsg(); }); btnCopy.Click += menuMsgViewCopyAll_Click; diff --git a/v2rayN/v2rayN/Views/ProfilesSelectWindow.xaml.cs b/v2rayN/v2rayN/Views/ProfilesSelectWindow.xaml.cs index 07fc2230..8d4fb1db 100644 --- a/v2rayN/v2rayN/Views/ProfilesSelectWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/ProfilesSelectWindow.xaml.cs @@ -35,7 +35,7 @@ public partial class ProfilesSelectWindow ViewModel.ProfilesFocusInteraction.RegisterHandler(interaction => { lstProfiles.Focus(); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); }); diff --git a/v2rayN/v2rayN/Views/ProfilesView.xaml.cs b/v2rayN/v2rayN/Views/ProfilesView.xaml.cs index 4230f89d..47683b31 100644 --- a/v2rayN/v2rayN/Views/ProfilesView.xaml.cs +++ b/v2rayN/v2rayN/Views/ProfilesView.xaml.cs @@ -111,13 +111,13 @@ public partial class ProfilesView { var strData = interaction.Input; WindowsUtils.SetClipboardData(strData); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.ProfilesFocusInteraction.RegisterHandler(interaction => { lstProfiles.Focus(); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.ShareServerInteraction.RegisterHandler(async interaction => @@ -125,23 +125,23 @@ public partial class ProfilesView var url = interaction.Input; if (url.IsNullOrEmpty()) { - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); return; } await ShareServer(url); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.DispatcherRefreshServersBizInteraction.RegisterHandler(interaction => { Application.Current?.Dispatcher.Invoke(RefreshServersBiz, DispatcherPriority.Normal); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.AdjustMainLvColWidthInteraction.RegisterHandler(interaction => { AutofitColumnWidth(); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); AppEvents.AppExitRequested diff --git a/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml.cs b/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml.cs index 2a7ace02..0df2007c 100644 --- a/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml.cs @@ -19,7 +19,7 @@ public partial class RoutingRuleDetailsWindow this.WhenActivated(disposables => { this.WhenAnyValue(v => v.ViewModel.SelectedSource) - .WhereNotNull() + .KeepNotNull() .Subscribe(InitializeData) .DisposeWith(disposables); diff --git a/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs index ae7253f4..e82e11e8 100644 --- a/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs @@ -57,7 +57,7 @@ public partial class RoutingRuleSettingWindow { var strData = interaction.Input; WindowsUtils.SetClipboardData(strData); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.ReadTextFromClipboardInteraction.RegisterHandler(interaction => diff --git a/v2rayN/v2rayN/Views/StatusBarView.xaml.cs b/v2rayN/v2rayN/Views/StatusBarView.xaml.cs index db1739ac..4dab2d75 100644 --- a/v2rayN/v2rayN/Views/StatusBarView.xaml.cs +++ b/v2rayN/v2rayN/Views/StatusBarView.xaml.cs @@ -18,10 +18,10 @@ public partial class StatusBarView this.WhenActivated(disposables => { //system proxy - this.OneWayBind(ViewModel, vm => vm.BlSystemProxyClear, v => v.menuSystemProxyClear2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables); - this.OneWayBind(ViewModel, vm => vm.BlSystemProxySet, v => v.menuSystemProxySet2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables); - this.OneWayBind(ViewModel, vm => vm.BlSystemProxyNothing, v => v.menuSystemProxyNothing2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables); - this.OneWayBind(ViewModel, vm => vm.BlSystemProxyPac, v => v.menuSystemProxyPac2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables); + this.OneWayBind(ViewModel, vm => vm.BlSystemProxyClear, v => v.menuSystemProxyClear2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, viewModelToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables); + this.OneWayBind(ViewModel, vm => vm.BlSystemProxySet, v => v.menuSystemProxySet2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, viewModelToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables); + this.OneWayBind(ViewModel, vm => vm.BlSystemProxyNothing, v => v.menuSystemProxyNothing2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, viewModelToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables); + this.OneWayBind(ViewModel, vm => vm.BlSystemProxyPac, v => v.menuSystemProxyPac2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, viewModelToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SystemProxyClearCmd, v => v.menuSystemProxyClear).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SystemProxySetCmd, v => v.menuSystemProxySet).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SystemProxyNothingCmd, v => v.menuSystemProxyNothing).DisposeWith(disposables); @@ -66,13 +66,13 @@ public partial class StatusBarView { var strData = interaction.Input; WindowsUtils.SetClipboardData(strData); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); ViewModel.DispatcherRefreshIconInteraction.RegisterHandler(interaction => { Application.Current?.Dispatcher.Invoke(async () => await RefreshIcon(), DispatcherPriority.Normal); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); }); diff --git a/v2rayN/v2rayN/Views/SubSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/SubSettingWindow.xaml.cs index 52bb231c..ed8ec027 100644 --- a/v2rayN/v2rayN/Views/SubSettingWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/SubSettingWindow.xaml.cs @@ -40,11 +40,11 @@ public partial class SubSettingWindow var url = interaction.Input; if (url.IsNullOrEmpty()) { - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); return; } await ShareSub(url); - interaction.SetOutput(Unit.Default); + interaction.SetOutput(RxVoid.Default); }).DisposeWith(disposables); }); WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme); diff --git a/v2rayN/v2rayN/v2rayN.csproj b/v2rayN/v2rayN/v2rayN.csproj index d8863845..237a1271 100644 --- a/v2rayN/v2rayN/v2rayN.csproj +++ b/v2rayN/v2rayN/v2rayN.csproj @@ -16,8 +16,9 @@ - - true + + all + runtime; build; native; contentfiles; analyzers; buildtransitive