mirror of
https://github.com/2dust/v2rayN.git
synced 2025-10-26 10:14:42 +00:00
Compare commits
11 commits
377670eff8
...
65b78ce6f9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65b78ce6f9 | ||
|
|
e96a4818c4 | ||
|
|
0377e7ce19 | ||
|
|
6929886b3e | ||
|
|
721d70c8c7 | ||
|
|
27b45aee83 | ||
|
|
18ac76e683 | ||
|
|
3e1e23a524 | ||
|
|
534c7ab444 | ||
|
|
c2c13ad318 | ||
|
|
3a21596d95 |
25 changed files with 227 additions and 102 deletions
|
|
@ -1,7 +1,7 @@
|
|||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>7.14.11</Version>
|
||||
<Version>7.14.12</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@
|
|||
<PackageVersion Include="ReactiveUI" Version="20.4.1" />
|
||||
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||
<PackageVersion Include="ReactiveUI.WPF" Version="20.4.1" />
|
||||
<PackageVersion Include="Semi.Avalonia" Version="11.2.1.9" />
|
||||
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.9" />
|
||||
<PackageVersion Include="Splat.NLog" Version="16.2.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="17.0.1" />
|
||||
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
|
||||
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
|
||||
<PackageVersion Include="WebDav.Client" Version="2.9.0" />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using QRCoder;
|
||||
using QRCoder.Exceptions;
|
||||
using SkiaSharp;
|
||||
using ZXing.SkiaSharp;
|
||||
|
||||
|
|
@ -8,10 +9,45 @@ public class QRCodeUtils
|
|||
{
|
||||
public static byte[]? GenQRCode(string? url)
|
||||
{
|
||||
if (url.IsNullOrEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
using QRCodeGenerator qrGenerator = new();
|
||||
using var qrCodeData = qrGenerator.CreateQrCode(url ?? string.Empty, QRCodeGenerator.ECCLevel.Q);
|
||||
using PngByteQRCode qrCode = new(qrCodeData);
|
||||
return qrCode.GetGraphic(20);
|
||||
DataTooLongException? lastDtle = null;
|
||||
|
||||
var levels = new[]
|
||||
{
|
||||
QRCodeGenerator.ECCLevel.H,
|
||||
QRCodeGenerator.ECCLevel.Q,
|
||||
QRCodeGenerator.ECCLevel.M,
|
||||
QRCodeGenerator.ECCLevel.L
|
||||
};
|
||||
foreach (var level in levels)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var qrCodeData = qrGenerator.CreateQrCode(url, level);
|
||||
using PngByteQRCode qrCode = new(qrCodeData);
|
||||
return qrCode.GetGraphic(20);
|
||||
}
|
||||
catch (DataTooLongException ex)
|
||||
{
|
||||
lastDtle = ex;
|
||||
continue;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastDtle != null)
|
||||
{
|
||||
throw lastDtle;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string? ParseBarcode(string? fileName)
|
||||
|
|
|
|||
|
|
@ -598,6 +598,7 @@ public class Global
|
|||
{ "cloudflare-dns.com", new List<string> { "104.16.249.249", "104.16.248.249", "2606:4700::6810:f8f9", "2606:4700::6810:f9f9" } },
|
||||
{ "dns.cloudflare.com", new List<string> { "104.16.132.229", "104.16.133.229", "2606:4700::6810:84e5", "2606:4700::6810:85e5" } },
|
||||
{ "dot.pub", new List<string> { "1.12.12.12", "120.53.53.53" } },
|
||||
{ "doh.pub", new List<string> { "1.12.12.12", "120.53.53.53" } },
|
||||
{ "dns.quad9.net", new List<string> { "9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9" } },
|
||||
{ "dns.yandex.net", new List<string> { "77.88.8.8", "77.88.8.1", "2a02:6b8::feed:0ff", "2a02:6b8:0:1::feed:0ff" } },
|
||||
{ "dns.sb", new List<string> { "185.222.222.222", "2a09::" } },
|
||||
|
|
|
|||
|
|
@ -6,16 +6,22 @@ namespace ServiceLib.Handler;
|
|||
public static class AppEvents
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1214,11 +1214,11 @@ public static class ConfigHandler
|
|||
CoreType = ECoreType.sing_box,
|
||||
ConfigType = EConfigType.SOCKS,
|
||||
Address = Global.Loopback,
|
||||
Sni = node.Address, //Tun2SocksAddress
|
||||
SpiderX = node.Address, // Tun2SocksAddress
|
||||
Port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks)
|
||||
};
|
||||
}
|
||||
else if ((node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0))
|
||||
else if (node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0)
|
||||
{
|
||||
var preCoreType = config.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
|
||||
itemSocks = new ProfileItem()
|
||||
|
|
|
|||
|
|
@ -43,16 +43,7 @@ public partial class CoreConfigSingboxService
|
|||
});
|
||||
}
|
||||
|
||||
// Tun2SocksAddress
|
||||
if (node != null && Utils.IsDomain(node.Address))
|
||||
{
|
||||
singboxConfig.dns.rules ??= new List<Rule4Sbox>();
|
||||
singboxConfig.dns.rules.Insert(0, new Rule4Sbox
|
||||
{
|
||||
server = Global.SingboxOutboundResolverTag,
|
||||
domain = [node.Address],
|
||||
});
|
||||
}
|
||||
await GenOutboundDnsRule(node, singboxConfig, Global.SingboxOutboundResolverTag);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -346,16 +337,7 @@ public partial class CoreConfigSingboxService
|
|||
await GenDnsDomainsLegacyCompatible(singboxConfig, item);
|
||||
}
|
||||
|
||||
// Tun2SocksAddress
|
||||
if (node != null && Utils.IsDomain(node.Address))
|
||||
{
|
||||
singboxConfig.dns.rules ??= new List<Rule4Sbox>();
|
||||
singboxConfig.dns.rules.Insert(0, new Rule4Sbox
|
||||
{
|
||||
server = Global.SingboxFinalResolverTag,
|
||||
domain = [node.Address],
|
||||
});
|
||||
}
|
||||
await GenOutboundDnsRule(node, singboxConfig, Global.SingboxFinalResolverTag);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -425,6 +407,37 @@ public partial class CoreConfigSingboxService
|
|||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenOutboundDnsRule(ProfileItem? node, SingboxConfig singboxConfig, string? server)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var domain = string.Empty;
|
||||
if (Utils.IsDomain(node.Address)) // normal outbound
|
||||
{
|
||||
domain = node.Address;
|
||||
}
|
||||
else if (node.Address == Global.Loopback && node.SpiderX.IsNotEmpty() && Utils.IsDomain(node.SpiderX)) // Tun2SocksAddress
|
||||
{
|
||||
domain = node.SpiderX;
|
||||
}
|
||||
if (domain.IsNullOrEmpty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
singboxConfig.dns.rules ??= new List<Rule4Sbox>();
|
||||
singboxConfig.dns.rules.Insert(0, new Rule4Sbox
|
||||
{
|
||||
server = server,
|
||||
domain = [domain],
|
||||
});
|
||||
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private static Server4Sbox? ParseDnsAddress(string address)
|
||||
{
|
||||
var addressFirst = address?.Split(address.Contains(',') ? ',' : ';').FirstOrDefault()?.Trim();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ using System.Reactive;
|
|||
using System.Reactive.Concurrency;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
|
||||
namespace ServiceLib.ViewModels;
|
||||
|
||||
|
|
@ -240,7 +239,6 @@ public class MainWindowViewModel : MyReactiveObject
|
|||
BlReloadEnabled = true;
|
||||
await Reload();
|
||||
await AutoHideStartup();
|
||||
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
|
||||
}
|
||||
|
||||
#endregion Init
|
||||
|
|
@ -301,7 +299,7 @@ public class MainWindowViewModel : MyReactiveObject
|
|||
|
||||
private void RefreshSubscriptions()
|
||||
{
|
||||
Locator.Current.GetService<ProfilesViewModel>()?.RefreshSubscriptions();
|
||||
AppEvents.SubscriptionsRefreshRequested.OnNext(Unit.Default);
|
||||
}
|
||||
|
||||
#endregion Servers && Groups
|
||||
|
|
@ -433,7 +431,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();
|
||||
}
|
||||
}
|
||||
|
|
@ -444,7 +442,7 @@ public class MainWindowViewModel : MyReactiveObject
|
|||
if (ret == true)
|
||||
{
|
||||
await ConfigHandler.InitBuiltinRouting(_config);
|
||||
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
|
||||
AppEvents.RoutingsMenuRefreshRequested.OnNext(Unit.Default);
|
||||
await Reload();
|
||||
}
|
||||
}
|
||||
|
|
@ -518,9 +516,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)
|
||||
|
|
@ -530,19 +534,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()
|
||||
|
|
@ -574,7 +570,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);
|
||||
|
|
|
|||
|
|
@ -240,11 +240,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();
|
||||
|
|
@ -380,7 +390,7 @@ public class ProfilesViewModel : MyReactiveObject
|
|||
await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null);
|
||||
}
|
||||
|
||||
public async Task RefreshSubscriptions()
|
||||
private async Task RefreshSubscriptions()
|
||||
{
|
||||
SubItems.Clear();
|
||||
|
||||
|
|
@ -565,7 +575,7 @@ public class ProfilesViewModel : MyReactiveObject
|
|||
await SetDefaultServer(SelectedProfile.IndexId);
|
||||
}
|
||||
|
||||
public async Task SetDefaultServer(string? indexId)
|
||||
private async Task SetDefaultServer(string? indexId)
|
||||
{
|
||||
if (indexId.IsNullOrEmpty())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ 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>();
|
||||
|
|
@ -209,6 +212,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();
|
||||
|
|
@ -329,7 +352,7 @@ public class StatusBarViewModel : MyReactiveObject
|
|||
{
|
||||
return;
|
||||
}
|
||||
Locator.Current.GetService<ProfilesViewModel>()?.SetDefaultServer(SelectedServer.ID);
|
||||
AppEvents.SetDefaultServerRequested.OnNext(SelectedServer.ID);
|
||||
}
|
||||
|
||||
public async Task TestServerAvailability()
|
||||
|
|
@ -364,7 +387,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 +416,7 @@ public class StatusBarViewModel : MyReactiveObject
|
|||
}
|
||||
}
|
||||
|
||||
public async Task RefreshRoutingsMenu()
|
||||
private async Task RefreshRoutingsMenu()
|
||||
{
|
||||
RoutingItems.Clear();
|
||||
|
||||
|
|
@ -501,7 +524,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)}");
|
||||
|
|
|
|||
|
|
@ -16,9 +16,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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,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;
|
||||
|
|
@ -259,7 +259,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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,19 +4,25 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="480"
|
||||
d:DesignWidth="400"
|
||||
xmlns:sys="clr-namespace:System;assembly=netstandard"
|
||||
d:DesignHeight="600"
|
||||
d:DesignWidth="600"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<sys:Double x:Key="QrcodeWidth">500</sys:Double>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="32" RowDefinitions="Auto,Auto">
|
||||
<Image
|
||||
Name="imgQrcode"
|
||||
Width="300"
|
||||
Height="300" />
|
||||
Width="{StaticResource QrcodeWidth}"
|
||||
Height="{StaticResource QrcodeWidth}" />
|
||||
|
||||
<TextBox
|
||||
x:Name="txtContent"
|
||||
Grid.Row="1"
|
||||
Width="300"
|
||||
Width="{StaticResource QrcodeWidth}"
|
||||
MaxHeight="100"
|
||||
Margin="{StaticResource MarginTb8}"
|
||||
VerticalAlignment="Center"
|
||||
|
|
|
|||
|
|
@ -23,8 +23,16 @@ public partial class QrcodeView : UserControl
|
|||
|
||||
private Bitmap? GetQRCode(string? url)
|
||||
{
|
||||
var bytes = QRCodeUtils.GenQRCode(url);
|
||||
return ByteToBitmap(bytes);
|
||||
try
|
||||
{
|
||||
var bytes = QRCodeUtils.GenQRCode(url);
|
||||
return ByteToBitmap(bytes);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog("GetQRCode", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Bitmap? ByteToBitmap(byte[]? bytes)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
24
v2rayN/v2rayN.slnx
Normal file
24
v2rayN/v2rayN.slnx
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<Solution>
|
||||
<Folder Name="/GitHub Action/">
|
||||
<File Path="../.github/workflows/build-all.yml" />
|
||||
<File Path="../.github/workflows/build-linux.yml" />
|
||||
<File Path="../.github/workflows/build-osx.yml" />
|
||||
<File Path="../.github/workflows/build-windows-desktop.yml" />
|
||||
<File Path="../.github/workflows/build-windows.yml" />
|
||||
<File Path="../.github/workflows/winget-publish.yml" />
|
||||
<File Path="../package-appimage.sh" />
|
||||
<File Path="../package-debian.sh" />
|
||||
<File Path="../package-osx.sh" />
|
||||
<File Path="../package-release-zip.sh" />
|
||||
<File Path="../pkg2appimage.yml" />
|
||||
</Folder>
|
||||
<Folder Name="/Solution Files/">
|
||||
<File Path="Directory.Build.props" />
|
||||
<File Path="Directory.Packages.props" />
|
||||
</Folder>
|
||||
<Project Path="AmazTool/AmazTool.csproj" />
|
||||
<Project Path="GlobalHotKeys/src/GlobalHotKeys/GlobalHotKeys.csproj" />
|
||||
<Project Path="ServiceLib/ServiceLib.csproj" />
|
||||
<Project Path="v2rayN.Desktop/v2rayN.Desktop.csproj" />
|
||||
<Project Path="v2rayN/v2rayN.csproj" />
|
||||
</Solution>
|
||||
|
|
@ -20,8 +20,9 @@ public class QRCodeUtils
|
|||
var qrCodeImage = ServiceLib.Common.QRCodeUtils.GenQRCode(strContent);
|
||||
return qrCodeImage is null ? null : ByteToImage(qrCodeImage);
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog("GetQRCode", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -32,8 +33,8 @@ public class QRCodeUtils
|
|||
{
|
||||
GetDpi(window, out var dpiX, out var dpiY);
|
||||
|
||||
var left = (int)(SystemParameters.WorkArea.Left);
|
||||
var top = (int)(SystemParameters.WorkArea.Top);
|
||||
var left = (int)SystemParameters.WorkArea.Left;
|
||||
var top = (int)SystemParameters.WorkArea.Top;
|
||||
var width = (int)(SystemParameters.WorkArea.Width / dpiX);
|
||||
var height = (int)(SystemParameters.WorkArea.Height / dpiY);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 =>
|
||||
|
|
|
|||
|
|
@ -249,7 +249,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -287,11 +287,7 @@ public partial class MainWindow
|
|||
var clipboardData = WindowsUtils.GetClipboardData();
|
||||
if (clipboardData.IsNotEmpty())
|
||||
{
|
||||
var service = Locator.Current.GetService<MainWindowViewModel>();
|
||||
if (service != null)
|
||||
{
|
||||
_ = service.AddServerViaClipboardAsync(clipboardData);
|
||||
}
|
||||
ViewModel?.AddServerViaClipboardAsync(clipboardData);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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 =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<UserControl
|
||||
<UserControl
|
||||
x:Class="v2rayN.Views.QrcodeView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
|
|
@ -6,28 +6,33 @@
|
|||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="300"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
d:DesignHeight="600"
|
||||
d:DesignWidth="600"
|
||||
Style="{StaticResource ViewGlobal}"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<sys:Double x:Key="QrcodeWidth">500</sys:Double>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="32">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="60" />
|
||||
<RowDefinition Height="80" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Image
|
||||
x:Name="imgQrcode"
|
||||
Grid.Row="0"
|
||||
Width="300"
|
||||
Height="300"
|
||||
Width="{StaticResource QrcodeWidth}"
|
||||
Height="{StaticResource QrcodeWidth}"
|
||||
Stretch="UniformToFill" />
|
||||
|
||||
<TextBox
|
||||
x:Name="txtContent"
|
||||
Grid.Row="1"
|
||||
Width="300"
|
||||
Width="{StaticResource QrcodeWidth}"
|
||||
Margin="0,8"
|
||||
VerticalAlignment="Center"
|
||||
IsReadOnly="True"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue