Compare commits

...

9 commits

Author SHA1 Message Date
DHR60
727b924c41
Merge 11924b545f into faff8e4ea2 2025-09-24 18:45:20 +08:00
2dust
faff8e4ea2 Remove secret data from mihomo configuration
Some checks are pending
release Linux / build (Release) (push) Waiting to run
release macOS / build (Release) (push) Waiting to run
release Windows desktop (Avalonia UI) / build (Release) (push) Waiting to run
release Windows / build (Release) (push) Waiting to run
2025-09-24 18:41:00 +08:00
2dust
6b85aa0b03 Remove Splat.NLog package 2025-09-24 10:57:23 +08:00
2dust
671678724b Optimization and improvement, using event subscribers 2025-09-24 10:57:06 +08:00
2dust
e96a4818c4 Optimization and improvement
Some checks are pending
release Linux / build (Release) (push) Waiting to run
release macOS / build (Release) (push) Waiting to run
release Windows desktop (Avalonia UI) / build (Release) (push) Waiting to run
release Windows / build (Release) (push) Waiting to run
2025-09-23 15:31:19 +08:00
2dust
0377e7ce19 Optimization and improvement, using event subscribers 2025-09-23 14:27:42 +08:00
2dust
6929886b3e Optimization and improvement, using event subscribers 2025-09-23 12:08:43 +08:00
2dust
721d70c8c7 Update Directory.Packages.props 2025-09-23 11:39:57 +08:00
2dust
27b45aee83 Optimization and improvement, using event subscribers 2025-09-23 11:39:55 +08:00
20 changed files with 183 additions and 153 deletions

View file

@ -20,11 +20,11 @@
<PackageVersion Include="ReactiveUI.WPF" Version="20.4.1" />
<PackageVersion Include="Semi.Avalonia" Version="11.2.1.10" />
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.10" />
<PackageVersion Include="Splat.NLog" Version="16.2.1" />
<PackageVersion Include="NLog" Version="6.0.4" />
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
<PackageVersion Include="WebDav.Client" Version="2.9.0" />
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
</ItemGroup>
</Project>
</Project>

View file

@ -12,7 +12,6 @@ public enum EViewAction
ProfilesFocus,
ShareSub,
ShareServer,
ShowHideWindow,
ScanScreenTask,
ScanImageTask,
BrowseServer,

View file

@ -5,17 +5,29 @@ namespace ServiceLib.Handler;
public static class AppEvents
{
public static readonly Subject<Unit> ReloadRequested = new();
public static readonly Subject<bool?> ShowHideWindowRequested = new();
public static readonly Subject<Unit> AddServerViaScanRequested = new();
public static readonly Subject<Unit> AddServerViaClipboardRequested = new();
public static readonly Subject<bool> SubscriptionsUpdateRequested = new();
public static readonly Subject<Unit> ProfilesRefreshRequested = new();
public static readonly Subject<Unit> SubscriptionsRefreshRequested = new();
public static readonly Subject<Unit> ProxiesReloadRequested = new();
public static readonly Subject<ServerSpeedItem> DispatcherStatisticsRequested = new();
public static readonly Subject<string> SendSnackMsgRequested = new();
public static readonly Subject<string> SendMsgViewRequested = new();
public static readonly Subject<Unit> AppExitRequested = new();
public static readonly Subject<bool> ShutdownRequested = new();
public static readonly Subject<Unit> AdjustMainLvColWidthRequested = new();
public static readonly Subject<ServerSpeedItem> DispatcherStatisticsRequested = new();
public static readonly Subject<string> SetDefaultServerRequested = new();
public static readonly Subject<Unit> RoutingsMenuRefreshRequested = new();
public static readonly Subject<Unit> TestServerRequested = new();
public static readonly Subject<Unit> InboundDisplayRequested = new();
public static readonly Subject<ESysProxyType> SysProxyChangeRequested = new();
}

View file

@ -124,6 +124,12 @@ public sealed class AppManager
AppEvents.ShutdownRequested.OnNext(byUser);
}
public async Task RebootAsAdmin()
{
ProcUtils.RebootAsAdmin();
await AppManager.Instance.AppExitAsync(true);
}
#endregion App
#region Config

View file

@ -11,7 +11,7 @@
</PackageReference>
<PackageReference Include="ReactiveUI.Fody" />
<PackageReference Include="sqlite-net-pcl" />
<PackageReference Include="Splat.NLog" />
<PackageReference Include="NLog" />
<PackageReference Include="WebDav.Client" />
<PackageReference Include="YamlDotNet" />
<PackageReference Include="QRCoder" />

View file

@ -79,6 +79,7 @@ public class CoreConfigClashService
//external-controller
fileContent["external-controller"] = $"{Global.Loopback}:{AppManager.Instance.StatePort2}";
fileContent.Remove("secret");
//allow-lan
if (_config.Inbound.First().AllowLANConn)
{

View file

@ -2,11 +2,9 @@ using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Runtime.InteropServices;
using DynamicData;
using DynamicData.Binding;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
namespace ServiceLib.ViewModels;
@ -225,11 +223,11 @@ public class CheckUpdateViewModel : MyReactiveObject
{
if (blReload)
{
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
AppEvents.ReloadRequested.OnNext(Unit.Default);
}
else
{
Locator.Current.GetService<MainWindowViewModel>()?.CloseCore();
await CoreManager.Instance.CoreStop();
}
}

View file

@ -69,6 +69,8 @@ public class ClashProxiesViewModel : MyReactiveObject
SortingSelected = _config.ClashUIItem.ProxiesSorting;
RuleModeSelected = (int)_config.ClashUIItem.RuleMode;
#region WhenAnyValue && ReactiveCommand
this.WhenAnyValue(
x => x.SelectedGroup,
y => y != null && y.Name.IsNotEmpty())
@ -89,6 +91,17 @@ public class ClashProxiesViewModel : MyReactiveObject
y => y == true)
.Subscribe(c => { _config.ClashUIItem.ProxiesAutoRefresh = AutoRefresh; });
#endregion WhenAnyValue && ReactiveCommand
#region AppEvents
AppEvents.ProxiesReloadRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async _ => await ProxiesReload());
#endregion AppEvents
_ = Init();
}

View file

@ -1,8 +1,8 @@
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
namespace ServiceLib.ViewModels;
@ -194,7 +194,7 @@ public class MainWindowViewModel : MyReactiveObject
});
RebootAsAdminCmd = ReactiveCommand.CreateFromTask(async () =>
{
await RebootAsAdmin();
await AppManager.Instance.RebootAsAdmin();
});
ClearServerStatisticsCmd = ReactiveCommand.CreateFromTask(async () =>
{
@ -227,6 +227,30 @@ public class MainWindowViewModel : MyReactiveObject
#endregion WhenAnyValue && ReactiveCommand
#region AppEvents
AppEvents.ReloadRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async _ => await Reload());
AppEvents.AddServerViaScanRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async _ => await AddServerViaScanAsync());
AppEvents.AddServerViaClipboardRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async _ => await AddServerViaClipboardAsync(null));
AppEvents.SubscriptionsUpdateRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async blProxy => await UpdateSubscriptionProcess("", blProxy));
#endregion AppEvents
_ = Init();
}
@ -251,7 +275,6 @@ public class MainWindowViewModel : MyReactiveObject
BlReloadEnabled = true;
await Reload();
await AutoHideStartup();
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
}
#endregion Init
@ -294,11 +317,6 @@ public class MainWindowViewModel : MyReactiveObject
AppEvents.DispatcherStatisticsRequested.OnNext(update);
}
public void ShowHideWindow(bool? blShow)
{
_updateView?.Invoke(EViewAction.ShowHideWindow, blShow);
}
#endregion Actions
#region Servers && Groups
@ -312,7 +330,7 @@ public class MainWindowViewModel : MyReactiveObject
private void RefreshSubscriptions()
{
Locator.Current.GetService<ProfilesViewModel>()?.RefreshSubscriptions();
AppEvents.SubscriptionsRefreshRequested.OnNext(Unit.Default);
}
#endregion Servers && Groups
@ -448,7 +466,7 @@ public class MainWindowViewModel : MyReactiveObject
var ret = await _updateView?.Invoke(EViewAction.OptionSettingWindow, null);
if (ret == true)
{
Locator.Current.GetService<StatusBarViewModel>()?.InboundDisplayStatus();
AppEvents.InboundDisplayRequested.OnNext(Unit.Default);
await Reload();
}
}
@ -459,7 +477,7 @@ public class MainWindowViewModel : MyReactiveObject
if (ret == true)
{
await ConfigHandler.InitBuiltinRouting(_config);
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
AppEvents.RoutingsMenuRefreshRequested.OnNext(Unit.Default);
await Reload();
}
}
@ -482,12 +500,6 @@ public class MainWindowViewModel : MyReactiveObject
}
}
public async Task RebootAsAdmin()
{
ProcUtils.RebootAsAdmin();
await AppManager.Instance.AppExitAsync(true);
}
private async Task ClearServerStatistics()
{
await StatisticsManager.Instance.ClearAllServerStatistics();
@ -533,9 +545,15 @@ public class MainWindowViewModel : MyReactiveObject
await SysProxyHandler.UpdateSysProxy(_config, false);
await Task.Delay(1000);
});
Locator.Current.GetService<StatusBarViewModel>()?.TestServerAvailability();
AppEvents.TestServerRequested.OnNext(Unit.Default);
RxApp.MainThreadScheduler.Schedule(() => _ = ReloadResult());
var showClashUI = _config.IsRunningCore(ECoreType.sing_box);
if (showClashUI)
{
AppEvents.ProxiesReloadRequested.OnNext(Unit.Default);
}
RxApp.MainThreadScheduler.Schedule(() => ReloadResult(showClashUI));
BlReloadEnabled = true;
if (_hasNextReloadJob)
@ -545,19 +563,11 @@ public class MainWindowViewModel : MyReactiveObject
}
}
public async Task ReloadResult()
private void ReloadResult(bool showClashUI)
{
// BlReloadEnabled = true;
//Locator.Current.GetService<StatusBarViewModel>()?.ChangeSystemProxyAsync(_config.systemProxyItem.sysProxyType, false);
ShowClashUI = _config.IsRunningCore(ECoreType.sing_box);
if (ShowClashUI)
{
Locator.Current.GetService<ClashProxiesViewModel>()?.ProxiesReload();
}
else
{
TabMainSelectedIndex = 0;
}
ShowClashUI = showClashUI;
TabMainSelectedIndex = showClashUI ? TabMainSelectedIndex : 0;
}
private async Task LoadCore()
@ -566,17 +576,11 @@ public class MainWindowViewModel : MyReactiveObject
await CoreManager.Instance.LoadCore(node);
}
public async Task CloseCore()
{
await ConfigHandler.SaveConfig(_config);
await CoreManager.Instance.CoreStop();
}
private async Task AutoHideStartup()
{
if (_config.UiItem.AutoHideStartup)
{
ShowHideWindow(false);
AppEvents.ShowHideWindowRequested.OnNext(false);
}
await Task.CompletedTask;
}
@ -589,7 +593,7 @@ public class MainWindowViewModel : MyReactiveObject
{
await ConfigHandler.ApplyRegionalPreset(_config, type);
await ConfigHandler.InitRouting(_config);
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
AppEvents.RoutingsMenuRefreshRequested.OnNext(Unit.Default);
await ConfigHandler.SaveConfig(_config);
await new UpdateService().UpdateGeoFileAll(_config, UpdateTaskHandler);

View file

@ -6,7 +6,6 @@ using DynamicData;
using DynamicData.Binding;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
namespace ServiceLib.ViewModels;
@ -250,11 +249,21 @@ public class ProfilesViewModel : MyReactiveObject
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async _ => await RefreshServersBiz());
AppEvents.SubscriptionsRefreshRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async _ => await RefreshSubscriptions());
AppEvents.DispatcherStatisticsRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async result => await UpdateStatistics(result));
AppEvents.SetDefaultServerRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async indexId => await SetDefaultServer(indexId));
#endregion AppEvents
_ = Init();
@ -276,7 +285,7 @@ public class ProfilesViewModel : MyReactiveObject
private void Reload()
{
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
AppEvents.ReloadRequested.OnNext(Unit.Default);
}
public async Task SetSpeedTestResult(SpeedTestResult result)
@ -390,7 +399,7 @@ public class ProfilesViewModel : MyReactiveObject
await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null);
}
public async Task RefreshSubscriptions()
private async Task RefreshSubscriptions()
{
SubItems.Clear();
@ -579,7 +588,7 @@ public class ProfilesViewModel : MyReactiveObject
await SetDefaultServer(SelectedProfile.IndexId);
}
public async Task SetDefaultServer(string? indexId)
private async Task SetDefaultServer(string? indexId)
{
if (indexId.IsNullOrEmpty())
{

View file

@ -5,12 +5,14 @@ using System.Text;
using DynamicData.Binding;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
namespace ServiceLib.ViewModels;
public class StatusBarViewModel : MyReactiveObject
{
private static readonly Lazy<StatusBarViewModel> _instance = new(() => new(null));
public static StatusBarViewModel Instance => _instance.Value;
#region ObservableCollection
public IObservableCollection<RoutingItem> RoutingItems { get; } = new ObservableCollectionExtended<RoutingItem>();
@ -146,17 +148,17 @@ public class StatusBarViewModel : MyReactiveObject
NotifyLeftClickCmd = ReactiveCommand.CreateFromTask(async () =>
{
Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(null);
AppEvents.ShowHideWindowRequested.OnNext(null);
await Task.CompletedTask;
});
ShowWindowCmd = ReactiveCommand.CreateFromTask(async () =>
{
Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(true);
AppEvents.ShowHideWindowRequested.OnNext(true);
await Task.CompletedTask;
});
HideWindowCmd = ReactiveCommand.CreateFromTask(async () =>
{
Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(false);
AppEvents.ShowHideWindowRequested.OnNext(false);
await Task.CompletedTask;
});
@ -209,6 +211,26 @@ public class StatusBarViewModel : MyReactiveObject
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async result => await UpdateStatistics(result));
AppEvents.RoutingsMenuRefreshRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async _ => await RefreshRoutingsMenu());
AppEvents.TestServerRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async _ => await TestServerAvailability());
AppEvents.InboundDisplayRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async _ => await InboundDisplayStatus());
AppEvents.SysProxyChangeRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async result => await SetListenerType(result));
#endregion AppEvents
_ = Init();
@ -252,23 +274,20 @@ public class StatusBarViewModel : MyReactiveObject
private async Task AddServerViaClipboard()
{
var service = Locator.Current.GetService<MainWindowViewModel>();
if (service != null)
await service.AddServerViaClipboardAsync(null);
AppEvents.AddServerViaClipboardRequested.OnNext(Unit.Default);
await Task.Delay(1000);
}
private async Task AddServerViaScan()
{
var service = Locator.Current.GetService<MainWindowViewModel>();
if (service != null)
await service.AddServerViaScanAsync();
AppEvents.AddServerViaScanRequested.OnNext(Unit.Default);
await Task.Delay(1000);
}
private async Task UpdateSubscriptionProcess(bool blProxy)
{
var service = Locator.Current.GetService<MainWindowViewModel>();
if (service != null)
await service.UpdateSubscriptionProcess("", blProxy);
AppEvents.SubscriptionsUpdateRequested.OnNext(blProxy);
await Task.Delay(1000);
}
private async Task RefreshServersBiz()
@ -329,7 +348,7 @@ public class StatusBarViewModel : MyReactiveObject
{
return;
}
Locator.Current.GetService<ProfilesViewModel>()?.SetDefaultServer(SelectedServer.ID);
AppEvents.SetDefaultServerRequested.OnNext(SelectedServer.ID);
}
public async Task TestServerAvailability()
@ -364,7 +383,7 @@ public class StatusBarViewModel : MyReactiveObject
#region System proxy and Routings
public async Task SetListenerType(ESysProxyType type)
private async Task SetListenerType(ESysProxyType type)
{
if (_config.SystemProxyItem.SysProxyType == type)
{
@ -393,7 +412,7 @@ public class StatusBarViewModel : MyReactiveObject
}
}
public async Task RefreshRoutingsMenu()
private async Task RefreshRoutingsMenu()
{
RoutingItems.Clear();
@ -430,7 +449,7 @@ public class StatusBarViewModel : MyReactiveObject
if (await ConfigHandler.SetDefaultRouting(_config, item) == 0)
{
NoticeManager.Instance.SendMessageEx(ResUI.TipChangeRouting);
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
AppEvents.ReloadRequested.OnNext(Unit.Default);
_updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null);
}
}
@ -463,7 +482,7 @@ public class StatusBarViewModel : MyReactiveObject
if (Utils.IsWindows())
{
_config.TunModeItem.EnableTun = false;
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
await AppManager.Instance.RebootAsAdmin();
return;
}
else
@ -477,7 +496,7 @@ public class StatusBarViewModel : MyReactiveObject
}
}
await ConfigHandler.SaveConfig(_config);
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
AppEvents.ReloadRequested.OnNext(Unit.Default);
}
private bool AllowEnableTun()
@ -501,7 +520,7 @@ public class StatusBarViewModel : MyReactiveObject
#region UI
public async Task InboundDisplayStatus()
private async Task InboundDisplayStatus()
{
StringBuilder sb = new();
sb.Append($"[{EInboundProtocol.mixed}:{AppManager.Instance.GetLocalPort(EInboundProtocol.socks)}");

View file

@ -1,8 +1,7 @@
using System.Reactive;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Splat;
using v2rayN.Desktop.Common;
using v2rayN.Desktop.Views;
namespace v2rayN.Desktop;
@ -16,9 +15,7 @@ public partial class App : Application
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
var ViewModel = new StatusBarViewModel(null);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(StatusBarViewModel));
DataContext = ViewModel;
DataContext = StatusBarViewModel.Instance;
}
public override void OnFrameworkInitializationCompleted()
@ -57,16 +54,8 @@ public partial class App : Application
{
if (desktop.MainWindow != null)
{
var clipboardData = await AvaUtils.GetClipboardData(desktop.MainWindow);
if (clipboardData.IsNullOrEmpty())
{
return;
}
var service = Locator.Current.GetService<MainWindowViewModel>();
if (service != null)
{
_ = service.AddServerViaClipboardAsync(clipboardData);
}
AppEvents.AddServerViaClipboardRequested.OnNext(Unit.Default);
await Task.Delay(1000);
}
}
}

View file

@ -3,7 +3,6 @@ using Avalonia.Input;
using Avalonia.ReactiveUI;
using DynamicData;
using ReactiveUI;
using Splat;
namespace v2rayN.Desktop.Views;
@ -13,7 +12,6 @@ public partial class ClashProxiesView : ReactiveUserControl<ClashProxiesViewMode
{
InitializeComponent();
ViewModel = new ClashProxiesViewModel(UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(ClashProxiesViewModel));
lstProxyDetails.DoubleTapped += LstProxyDetails_DoubleTapped;
this.KeyDown += ClashProxiesView_KeyDown;

View file

@ -10,7 +10,6 @@ using Avalonia.Threading;
using DialogHostAvalonia;
using MsBox.Avalonia.Enums;
using ReactiveUI;
using Splat;
using v2rayN.Desktop.Base;
using v2rayN.Desktop.Common;
using v2rayN.Desktop.Manager;
@ -20,7 +19,7 @@ namespace v2rayN.Desktop.Views;
public partial class MainWindow : WindowBase<MainWindowViewModel>
{
private static Config _config;
private WindowNotificationManager? _manager;
private readonly WindowNotificationManager? _manager;
private CheckUpdateView? _checkUpdateView;
private BackupAndRestoreView? _backupAndRestoreView;
private bool _blCloseByUser = false;
@ -40,7 +39,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
menuClose.Click += MenuClose_Click;
ViewModel = new MainWindowViewModel(UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
switch (_config.UiItem.MainGirdOrientation)
{
@ -155,6 +153,12 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(content => Shutdown(content))
.DisposeWith(disposables);
AppEvents.ShowHideWindowRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(blShow => ShowHideWindow(blShow))
.DisposeWith(disposables);
});
if (Utils.IsWindows())
@ -228,12 +232,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
case EViewAction.SubSettingWindow:
return await new SubSettingWindow().ShowDialog<bool>(this);
case EViewAction.ShowHideWindow:
Dispatcher.UIThread.Post(() =>
ShowHideWindow((bool?)obj),
DispatcherPriority.Default);
break;
case EViewAction.ScanScreenTask:
await ScanScreenTaskAsync();
break;
@ -243,11 +241,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
break;
case EViewAction.AddServerViaClipboard:
var clipboardData = await AvaUtils.GetClipboardData(this);
if (clipboardData.IsNotEmpty() && ViewModel != null)
{
await ViewModel.AddServerViaClipboardAsync(clipboardData);
}
await AddServerViaClipboardAsync();
break;
}
@ -266,7 +260,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
case EGlobalHotkey.SystemProxySet:
case EGlobalHotkey.SystemProxyUnchanged:
case EGlobalHotkey.SystemProxyPac:
Locator.Current.GetService<StatusBarViewModel>()?.SetListenerType((ESysProxyType)((int)e - 1));
AppEvents.SysProxyChangeRequested.OnNext((ESysProxyType)((int)e - 1));
break;
}
}
@ -302,11 +296,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
switch (e.Key)
{
case Key.V:
var clipboardData = await AvaUtils.GetClipboardData(this);
if (clipboardData.IsNotEmpty() && ViewModel != null)
{
await ViewModel.AddServerViaClipboardAsync(clipboardData);
}
await AddServerViaClipboardAsync();
break;
case Key.S:
@ -333,6 +323,15 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
ProcUtils.ProcessStart(Utils.GetBinPath("EnableLoopback.exe"));
}
public async Task AddServerViaClipboardAsync()
{
var clipboardData = await AvaUtils.GetClipboardData(this);
if (clipboardData.IsNotEmpty() && ViewModel != null)
{
await ViewModel.AddServerViaClipboardAsync(clipboardData);
}
}
public async Task ScanScreenTaskAsync()
{
//ShowHideWindow(false);

View file

@ -8,7 +8,6 @@ using Avalonia.Threading;
using DialogHostAvalonia;
using MsBox.Avalonia.Enums;
using ReactiveUI;
using Splat;
using v2rayN.Desktop.Common;
namespace v2rayN.Desktop.Views;
@ -48,7 +47,6 @@ public partial class ProfilesView : ReactiveUserControl<ProfilesViewModel>
//}
ViewModel = new ProfilesViewModel(UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(ProfilesViewModel));
this.WhenActivated(disposables =>
{

View file

@ -6,7 +6,6 @@ using Avalonia.ReactiveUI;
using Avalonia.Threading;
using DialogHostAvalonia;
using ReactiveUI;
using Splat;
using v2rayN.Desktop.Common;
namespace v2rayN.Desktop.Views;
@ -20,9 +19,8 @@ public partial class StatusBarView : ReactiveUserControl<StatusBarViewModel>
InitializeComponent();
_config = AppManager.Instance.Config;
//ViewModel = new StatusBarViewModel(UpdateViewHandler);
//Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(StatusBarViewModel));
ViewModel = Locator.Current.GetService<StatusBarViewModel>();
ViewModel = StatusBarViewModel.Instance;
ViewModel?.InitUpdateView(UpdateViewHandler);
txtRunningServerDisplay.Tapped += TxtRunningServerDisplay_Tapped;

View file

@ -1,7 +1,6 @@
using System.Reactive.Disposables;
using System.Windows.Input;
using ReactiveUI;
using Splat;
namespace v2rayN.Views;
@ -14,7 +13,6 @@ public partial class ClashProxiesView
{
InitializeComponent();
ViewModel = new ClashProxiesViewModel(UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(ClashProxiesViewModel));
lstProxyDetails.PreviewMouseDoubleClick += lstProxyDetails_PreviewMouseDoubleClick;
this.WhenActivated(disposables =>

View file

@ -6,10 +6,8 @@ using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;
using MaterialDesignThemes.Wpf;
using ReactiveUI;
using Splat;
using v2rayN.Manager;
namespace v2rayN.Views;
@ -37,7 +35,6 @@ public partial class MainWindow
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
ViewModel = new MainWindowViewModel(UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
switch (_config.UiItem.MainGirdOrientation)
{
@ -148,10 +145,16 @@ public partial class MainWindow
.DisposeWith(disposables);
AppEvents.ShutdownRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(content => Shutdown(content))
.DisposeWith(disposables);
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(content => Shutdown(content))
.DisposeWith(disposables);
AppEvents.ShowHideWindowRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(blShow => ShowHideWindow(blShow))
.DisposeWith(disposables);
});
this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
@ -217,13 +220,6 @@ public partial class MainWindow
case EViewAction.SubSettingWindow:
return (new SubSettingWindow().ShowDialog() ?? false);
case EViewAction.ShowHideWindow:
Application.Current?.Dispatcher.Invoke((() =>
{
ShowHideWindow((bool?)obj);
}), DispatcherPriority.Normal);
break;
case EViewAction.ScanScreenTask:
await ScanScreenTaskAsync();
break;
@ -233,11 +229,7 @@ public partial class MainWindow
break;
case EViewAction.AddServerViaClipboard:
var clipboardData = WindowsUtils.GetClipboardData();
if (clipboardData.IsNotEmpty())
{
ViewModel?.AddServerViaClipboardAsync(clipboardData);
}
await AddServerViaClipboardAsync();
break;
}
@ -256,7 +248,7 @@ public partial class MainWindow
case EGlobalHotkey.SystemProxySet:
case EGlobalHotkey.SystemProxyUnchanged:
case EGlobalHotkey.SystemProxyPac:
Locator.Current.GetService<StatusBarViewModel>()?.SetListenerType((ESysProxyType)((int)e - 1));
AppEvents.SysProxyChangeRequested.OnNext((ESysProxyType)((int)e - 1));
break;
}
}
@ -290,16 +282,7 @@ public partial class MainWindow
{
return;
}
var clipboardData = WindowsUtils.GetClipboardData();
if (clipboardData.IsNotEmpty())
{
var service = Locator.Current.GetService<MainWindowViewModel>();
if (service != null)
{
_ = service.AddServerViaClipboardAsync(clipboardData);
}
}
AddServerViaClipboardAsync().ContinueWith(_ => { });
break;
@ -333,6 +316,15 @@ public partial class MainWindow
ProcUtils.ProcessStart(Utils.GetBinPath("EnableLoopback.exe"));
}
public async Task AddServerViaClipboardAsync()
{
var clipboardData = WindowsUtils.GetClipboardData();
if (clipboardData.IsNotEmpty() && ViewModel != null)
{
await ViewModel.AddServerViaClipboardAsync(clipboardData);
}
}
private async Task ScanScreenTaskAsync()
{
ShowHideWindow(false);

View file

@ -8,7 +8,6 @@ using System.Windows.Media;
using System.Windows.Threading;
using MaterialDesignThemes.Wpf;
using ReactiveUI;
using Splat;
using v2rayN.Base;
using Point = System.Windows.Point;
@ -42,7 +41,6 @@ public partial class ProfilesView
}
ViewModel = new ProfilesViewModel(UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(ProfilesViewModel));
this.WhenActivated(disposables =>
{

View file

@ -3,7 +3,6 @@ using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using ReactiveUI;
using Splat;
using v2rayN.Manager;
namespace v2rayN.Views;
@ -16,8 +15,8 @@ public partial class StatusBarView
{
InitializeComponent();
_config = AppManager.Instance.Config;
ViewModel = new StatusBarViewModel(UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(StatusBarViewModel));
ViewModel = StatusBarViewModel.Instance;
ViewModel?.InitUpdateView(UpdateViewHandler);
menuExit.Click += menuExit_Click;
txtRunningServerDisplay.PreviewMouseDown += txtRunningInfoDisplay_MouseDoubleClick;