Compare commits

..

18 commits

Author SHA1 Message Date
DHR60
69e083f76f PreCheck 2025-09-14 20:54:03 +08:00
DHR60
4ae34ccb01 Adjust chained proxy, actual outbound is at the top
Based on actual network flow instead of data packets
2025-09-14 13:23:13 +08:00
DHR60
437b2bd4e6 Refactor 2025-09-13 15:11:10 +08:00
DHR60
81e4755dda Avoid duplicate tags 2025-09-13 15:05:18 +08:00
DHR60
9a78dcb61c Add group in traffic splitting support 2025-09-13 15:05:18 +08:00
DHR60
5bf1b374bd Add PolicyGroup include other Group support 2025-09-13 15:05:18 +08:00
DHR60
5030269fdd Add fallback support 2025-09-13 15:05:17 +08:00
DHR60
02ba731442 Fix 2025-09-13 15:05:17 +08:00
DHR60
c81b89b98c Add Proxy Chain support 2025-09-13 15:05:17 +08:00
DHR60
997d75cc22 Adjust UI 2025-09-13 15:05:17 +08:00
DHR60
17ff20d44a Add generate policy group 2025-09-13 15:05:17 +08:00
DHR60
fcbf477bb1 Add Policy Group support 2025-09-13 15:05:17 +08:00
DHR60
4bf89187a9 Rename 2025-09-13 15:05:17 +08:00
DHR60
c29c4796c7 Exclude specific profile types from selection 2025-09-13 15:05:17 +08:00
DHR60
14ea998a12 Fix right click not working 2025-09-13 15:05:17 +08:00
DHR60
13ed6e84e7 avalonia 2025-09-13 15:05:17 +08:00
DHR60
cfe515c5ac VM and wpf 2025-09-13 15:05:17 +08:00
DHR60
1e054cfc7d Multi Profile 2025-09-13 15:05:17 +08:00
13 changed files with 63 additions and 156 deletions

View file

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<Version>7.14.12</Version>
<Version>7.14.10</Version>
</PropertyGroup>
<PropertyGroup>

View file

@ -18,8 +18,8 @@
<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.10" />
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.10" />
<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="sqlite-net-pcl" Version="1.9.172" />
<PackageVersion Include="TaskScheduler" Version="2.12.2" />

View file

@ -1,5 +1,4 @@
using QRCoder;
using QRCoder.Exceptions;
using SkiaSharp;
using ZXing.SkiaSharp;
@ -9,46 +8,11 @@ public class QRCodeUtils
{
public static byte[]? GenQRCode(string? url)
{
if (url.IsNullOrEmpty())
{
return null;
}
using QRCodeGenerator qrGenerator = new();
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 var qrCodeData = qrGenerator.CreateQrCode(url ?? string.Empty, QRCodeGenerator.ECCLevel.Q);
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)
{

View file

@ -599,7 +599,6 @@ 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::" } },

View file

@ -1258,11 +1258,11 @@ public static class ConfigHandler
CoreType = ECoreType.sing_box,
ConfigType = EConfigType.SOCKS,
Address = Global.Loopback,
SpiderX = node.Address, // Tun2SocksAddress
Sni = node.Address, //Tun2SocksAddress
Port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks)
};
}
else if (node.ConfigType == EConfigType.Custom && node.ConfigType < EConfigType.Group && node.PreSocksPort > 0)
else if ((node.ConfigType == EConfigType.Custom && node.ConfigType < EConfigType.Group && node.PreSocksPort > 0))
{
var preCoreType = config.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
itemSocks = new ProfileItem()

View file

@ -43,7 +43,16 @@ public partial class CoreConfigSingboxService
});
}
await GenOutboundDnsRule(node, singboxConfig, Global.SingboxOutboundResolverTag);
// 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],
});
}
}
catch (Exception ex)
{
@ -337,7 +346,16 @@ public partial class CoreConfigSingboxService
await GenDnsDomainsLegacyCompatible(singboxConfig, item);
}
await GenOutboundDnsRule(node, singboxConfig, Global.SingboxFinalResolverTag);
// 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],
});
}
}
catch (Exception ex)
{
@ -407,37 +425,6 @@ 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();

View file

@ -38,7 +38,7 @@ public class CheckUpdateViewModel : MyReactiveObject
this.WhenAnyValue(
x => x.EnableCheckPreReleaseUpdate,
y => y == true)
.Subscribe(c => _config.CheckUpdateItem.CheckPreReleaseUpdate = EnableCheckPreReleaseUpdate);
.Subscribe(c => { _config.CheckUpdateItem.CheckPreReleaseUpdate = EnableCheckPreReleaseUpdate; });
RefreshCheckUpdateItems();
}
@ -158,8 +158,11 @@ public class CheckUpdateViewModel : MyReactiveObject
UpdatedPlusPlus(_geo, "");
}
}
await new UpdateService().UpdateGeoFileAll(_config, _updateUI)
.ContinueWith(t => UpdatedPlusPlus(_geo, ""));
await (new UpdateService()).UpdateGeoFileAll(_config, _updateUI)
.ContinueWith(t =>
{
UpdatedPlusPlus(_geo, "");
});
}
private async Task CheckUpdateN(bool preRelease)
@ -173,8 +176,11 @@ public class CheckUpdateViewModel : MyReactiveObject
UpdatedPlusPlus(_v2rayN, msg);
}
}
await new UpdateService().CheckUpdateGuiN(_config, _updateUI, preRelease)
.ContinueWith(t => UpdatedPlusPlus(_v2rayN, ""));
await (new UpdateService()).CheckUpdateGuiN(_config, _updateUI, preRelease)
.ContinueWith(t =>
{
UpdatedPlusPlus(_v2rayN, "");
});
}
private async Task CheckUpdateCore(CheckUpdateModel model, bool preRelease)
@ -190,8 +196,11 @@ public class CheckUpdateViewModel : MyReactiveObject
}
}
var type = (ECoreType)Enum.Parse(typeof(ECoreType), model.CoreType);
await new UpdateService().CheckUpdateCore(type, _config, _updateUI, preRelease)
.ContinueWith(t => UpdatedPlusPlus(model.CoreType, ""));
await (new UpdateService()).CheckUpdateCore(type, _config, _updateUI, preRelease)
.ContinueWith(t =>
{
UpdatedPlusPlus(model.CoreType, "");
});
}
private async Task UpdateFinished()
@ -302,7 +311,7 @@ public class CheckUpdateViewModel : MyReactiveObject
if (Utils.IsNonWindows())
{
var filesList = new DirectoryInfo(toPath).GetFiles().Select(u => u.FullName).ToList();
var filesList = (new DirectoryInfo(toPath)).GetFiles().Select(u => u.FullName).ToList();
foreach (var file in filesList)
{
await Utils.SetLinuxChmod(Path.Combine(toPath, item.CoreType.ToLower()));

View file

@ -601,10 +601,6 @@ public class ProfilesViewModel : MyReactiveObject
{
NoticeManager.Instance.SendMessage(msg);
}
if (msgs.Count > 0)
{
NoticeManager.Instance.Enqueue(msgs.First());
}
if (await ConfigHandler.SetDefaultServerIndex(_config, indexId) == 0)
{
@ -775,10 +771,6 @@ public class ProfilesViewModel : MyReactiveObject
{
NoticeManager.Instance.SendMessage(msg);
}
if (msgs.Count > 0)
{
NoticeManager.Instance.Enqueue(msgs.First());
}
if (blClipboard)
{
var result = await CoreConfigHandler.GenerateClientConfig(item, null);

View file

@ -4,25 +4,19 @@
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"
xmlns:sys="clr-namespace:System;assembly=netstandard"
d:DesignHeight="600"
d:DesignWidth="600"
d:DesignHeight="480"
d:DesignWidth="400"
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="{StaticResource QrcodeWidth}"
Height="{StaticResource QrcodeWidth}" />
Width="300"
Height="300" />
<TextBox
x:Name="txtContent"
Grid.Row="1"
Width="{StaticResource QrcodeWidth}"
Width="300"
MaxHeight="100"
Margin="{StaticResource MarginTb8}"
VerticalAlignment="Center"

View file

@ -22,18 +22,10 @@ public partial class QrcodeView : UserControl
}
private Bitmap? GetQRCode(string? url)
{
try
{
var bytes = QRCodeUtils.GenQRCode(url);
return ByteToBitmap(bytes);
}
catch (Exception ex)
{
Logging.SaveLog("GetQRCode", ex);
return null;
}
}
private Bitmap? ByteToBitmap(byte[]? bytes)
{

View file

@ -1,24 +0,0 @@
<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>

View file

@ -20,9 +20,8 @@ public class QRCodeUtils
var qrCodeImage = ServiceLib.Common.QRCodeUtils.GenQRCode(strContent);
return qrCodeImage is null ? null : ByteToImage(qrCodeImage);
}
catch (Exception ex)
catch
{
Logging.SaveLog("GetQRCode", ex);
return null;
}
}
@ -33,8 +32,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);

View file

@ -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,33 +6,28 @@
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"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
d:DesignHeight="600"
d:DesignWidth="600"
d:DesignHeight="300"
d:DesignWidth="300"
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="80" />
<RowDefinition Height="60" />
</Grid.RowDefinitions>
<Image
x:Name="imgQrcode"
Grid.Row="0"
Width="{StaticResource QrcodeWidth}"
Height="{StaticResource QrcodeWidth}"
Width="300"
Height="300"
Stretch="UniformToFill" />
<TextBox
x:Name="txtContent"
Grid.Row="1"
Width="{StaticResource QrcodeWidth}"
Width="300"
Margin="0,8"
VerticalAlignment="Center"
IsReadOnly="True"