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