Compare commits

...

3 commits

Author SHA1 Message Date
2dust
ad74b1584d Refactor dialog layouts
Some checks are pending
release Linux / build (Release) (push) Waiting to run
release Linux / rpm (push) Blocked by required conditions
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-11-21 20:30:41 +08:00
dependabot[bot]
514d76953a
Bump actions/checkout from 5.0.1 to 6.0.0 (#8359)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.1 to 6.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5.0.1...v6.0.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-21 15:57:37 +08:00
DHR60
5b82f17995
Fix (#8363)
* Fix

* AI-optimized code
2025-11-21 15:56:42 +08:00
13 changed files with 73 additions and 82 deletions

View file

@ -31,7 +31,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5.0.1 uses: actions/checkout@v6.0.0
with: with:
submodules: 'recursive' submodules: 'recursive'
fetch-depth: '0' fetch-depth: '0'
@ -110,7 +110,7 @@ jobs:
dnf -y install sudo git rpm-build rpmdevtools dnf-plugins-core rsync findutils tar gzip unzip which dnf -y install sudo git rpm-build rpmdevtools dnf-plugins-core rsync findutils tar gzip unzip which
- name: Checkout repo (for scripts) - name: Checkout repo (for scripts)
uses: actions/checkout@v5.0.1 uses: actions/checkout@v6.0.0
with: with:
submodules: 'recursive' submodules: 'recursive'
fetch-depth: '0' fetch-depth: '0'

View file

@ -26,7 +26,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5.0.1 uses: actions/checkout@v6.0.0
with: with:
submodules: 'recursive' submodules: 'recursive'
fetch-depth: '0' fetch-depth: '0'

View file

@ -26,7 +26,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5.0.1 uses: actions/checkout@v6.0.0
with: with:
submodules: 'recursive' submodules: 'recursive'
fetch-depth: '0' fetch-depth: '0'

View file

@ -27,7 +27,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5.0.1 uses: actions/checkout@v6.0.0
- name: Setup - name: Setup
uses: actions/setup-dotnet@v5.0.0 uses: actions/setup-dotnet@v5.0.0

View file

@ -73,13 +73,11 @@ public class ShadowsocksFmt : BaseFmt
const string beginMarker = "-----BEGIN CERTIFICATE-----\n"; const string beginMarker = "-----BEGIN CERTIFICATE-----\n";
const string endMarker = "\n-----END CERTIFICATE-----"; const string endMarker = "\n-----END CERTIFICATE-----";
var base64Start = beginMarker.Length; var base64Content = cert.Replace(beginMarker, "").Replace(endMarker, "").Trim();
var endIndex = cert.IndexOf(endMarker, base64Start, StringComparison.Ordinal);
var base64Content = cert.Substring(base64Start, endIndex - base64Start);
// https://github.com/shadowsocks/v2ray-plugin/blob/e9af1cdd2549d528deb20a4ab8d61c5fbe51f306/args.go#L172 // https://github.com/shadowsocks/v2ray-plugin/blob/e9af1cdd2549d528deb20a4ab8d61c5fbe51f306/args.go#L172
// Equal signs and commas [and backslashes] must be escaped with a backslash. // Equal signs and commas [and backslashes] must be escaped with a backslash.
base64Content = base64Content.Replace("\\", "\\\\").Replace("=", "\\=").Replace(",", "\\,"); base64Content = base64Content.Replace("=", "\\=");
pluginArgs += $"certRaw={base64Content};"; pluginArgs += $"certRaw={base64Content};";
} }
@ -251,7 +249,7 @@ public class ShadowsocksFmt : BaseFmt
{ {
var certBase64 = certRaw.Replace("certRaw=", ""); var certBase64 = certRaw.Replace("certRaw=", "");
certBase64 = certBase64.Replace("\\=", "=").Replace("\\,", ",").Replace("\\\\", "\\"); certBase64 = certBase64.Replace("\\=", "=");
const string beginMarker = "-----BEGIN CERTIFICATE-----\n"; const string beginMarker = "-----BEGIN CERTIFICATE-----\n";
const string endMarker = "\n-----END CERTIFICATE-----"; const string endMarker = "\n-----END CERTIFICATE-----";

View file

@ -10,6 +10,13 @@ public class ActionPrecheckManager(Config config)
private readonly Config _config = config; private readonly Config _config = config;
// sing-box supported transports for different protocol types
private static readonly HashSet<string> SingboxUnsupportedTransports = [nameof(ETransport.kcp), nameof(ETransport.xhttp)];
private static readonly HashSet<EConfigType> SingboxTransportSupportedProtocols =
[EConfigType.VMess, EConfigType.VLESS, EConfigType.Trojan, EConfigType.Shadowsocks];
private static readonly HashSet<string> SingboxShadowsocksAllowedTransports =
[nameof(ETransport.tcp), nameof(ETransport.ws), nameof(ETransport.quic)];
public async Task<List<string>> Check(string? indexId) public async Task<List<string>> Check(string? indexId)
{ {
if (indexId.IsNullOrEmpty()) if (indexId.IsNullOrEmpty())
@ -174,26 +181,16 @@ public class ActionPrecheckManager(Config config)
return errors; return errors;
} }
var net = item.GetNetwork() ?? item.Network; var net = item.GetNetwork();
if (coreType == ECoreType.sing_box) if (coreType == ECoreType.sing_box)
{ {
// sing-box does not support xhttp / kcp var transportError = ValidateSingboxTransport(item.ConfigType, net);
// sing-box does not support transports like ws/http/httpupgrade/etc. when the node is not vmess/trojan/vless if (transportError != null)
if (net is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
{ {
errors.Add(string.Format(ResUI.CoreNotSupportNetwork, nameof(ECoreType.sing_box), net)); errors.Add(transportError);
return errors; return errors;
} }
if (item.ConfigType is not (EConfigType.VMess or EConfigType.VLESS or EConfigType.Trojan))
{
if (net is nameof(ETransport.ws) or nameof(ETransport.http) or nameof(ETransport.h2) or nameof(ETransport.quic) or nameof(ETransport.httpupgrade))
{
errors.Add(string.Format(ResUI.CoreNotSupportProtocolTransport, nameof(ECoreType.sing_box), item.ConfigType.ToString(), net));
return errors;
}
}
} }
else if (coreType is ECoreType.Xray) else if (coreType is ECoreType.Xray)
{ {
@ -209,6 +206,31 @@ public class ActionPrecheckManager(Config config)
return errors; return errors;
} }
private static string? ValidateSingboxTransport(EConfigType configType, string net)
{
// sing-box does not support xhttp / kcp transports
if (SingboxUnsupportedTransports.Contains(net))
{
return string.Format(ResUI.CoreNotSupportNetwork, nameof(ECoreType.sing_box), net);
}
// sing-box does not support non-tcp transports for protocols other than vmess/trojan/vless/shadowsocks
if (!SingboxTransportSupportedProtocols.Contains(configType) && net != nameof(ETransport.tcp))
{
return string.Format(ResUI.CoreNotSupportProtocolTransport,
nameof(ECoreType.sing_box), configType.ToString(), net);
}
// sing-box shadowsocks only supports tcp/ws/quic transports
if (configType == EConfigType.Shadowsocks && !SingboxShadowsocksAllowedTransports.Contains(net))
{
return string.Format(ResUI.CoreNotSupportProtocolTransport,
nameof(ECoreType.sing_box), configType.ToString(), net);
}
return null;
}
private async Task<List<string>> ValidateRelatedNodesExistAndValid(ProfileItem? item) private async Task<List<string>> ValidateRelatedNodesExistAndValid(ProfileItem? item)
{ {
var errors = new List<string>(); var errors = new List<string>();

View file

@ -62,13 +62,11 @@ public partial class CoreConfigSingboxService
const string beginMarker = "-----BEGIN CERTIFICATE-----\n"; const string beginMarker = "-----BEGIN CERTIFICATE-----\n";
const string endMarker = "\n-----END CERTIFICATE-----"; const string endMarker = "\n-----END CERTIFICATE-----";
var base64Start = beginMarker.Length; var base64Content = cert.Replace(beginMarker, "").Replace(endMarker, "").Trim();
var endIndex = cert.IndexOf(endMarker, base64Start, StringComparison.Ordinal);
var base64Content = cert.Substring(base64Start, endIndex - base64Start);
// https://github.com/shadowsocks/v2ray-plugin/blob/e9af1cdd2549d528deb20a4ab8d61c5fbe51f306/args.go#L172 // https://github.com/shadowsocks/v2ray-plugin/blob/e9af1cdd2549d528deb20a4ab8d61c5fbe51f306/args.go#L172
// Equal signs and commas [and backslashes] must be escaped with a backslash. // Equal signs and commas [and backslashes] must be escaped with a backslash.
base64Content = base64Content.Replace("\\", "\\\\").Replace("=", "\\=").Replace(",", "\\,"); base64Content = base64Content.Replace("=", "\\=");
pluginArgs += $"certRaw={base64Content};"; pluginArgs += $"certRaw={base64Content};";
} }

View file

@ -90,13 +90,13 @@
<MenuItem x:Name="menuOpenTheFileLocation" Header="{x:Static resx:ResUI.menuOpenTheFileLocation}" /> <MenuItem x:Name="menuOpenTheFileLocation" Header="{x:Static resx:ResUI.menuOpenTheFileLocation}" />
</MenuItem> </MenuItem>
<MenuItem x:Name="menuReload" Header="{x:Static resx:ResUI.menuReload}" />
<MenuItem x:Name="menuHelp" Header="{x:Static resx:ResUI.menuHelp}"> <MenuItem x:Name="menuHelp" Header="{x:Static resx:ResUI.menuHelp}">
<MenuItem x:Name="menuCheckUpdate" Header="{x:Static resx:ResUI.menuCheckUpdate}" /> <MenuItem x:Name="menuCheckUpdate" Header="{x:Static resx:ResUI.menuCheckUpdate}" />
<Separator /> <Separator />
</MenuItem> </MenuItem>
<MenuItem x:Name="menuReload" Header="{x:Static resx:ResUI.menuReload}" />
<MenuItem x:Name="menuPromotion" Header="{x:Static resx:ResUI.menuPromotion}" /> <MenuItem x:Name="menuPromotion" Header="{x:Static resx:ResUI.menuPromotion}" />
<MenuItem x:Name="menuClose" Header="{x:Static resx:ResUI.menuExit}" /> <MenuItem x:Name="menuClose" Header="{x:Static resx:ResUI.menuExit}" />

View file

@ -1,4 +1,4 @@
<reactiveui:ReactiveUserControl <reactiveui:ReactiveUserControl
x:Class="v2rayN.Views.BackupAndRestoreView" x:Class="v2rayN.Views.BackupAndRestoreView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -23,15 +23,6 @@
</UserControl.Resources> </UserControl.Resources>
<DockPanel Margin="{StaticResource Margin8}"> <DockPanel Margin="{StaticResource Margin8}">
<DockPanel Margin="{StaticResource Margin8}" DockPanel.Dock="Bottom"> <DockPanel Margin="{StaticResource Margin8}" DockPanel.Dock="Bottom">
<Button
Width="100"
Margin="{StaticResource Margin8}"
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
Content="{x:Static resx:ResUI.menuClose}"
DockPanel.Dock="Right"
IsCancel="True"
Style="{StaticResource DefButton}" />
<TextBlock <TextBlock
x:Name="txtMsg" x:Name="txtMsg"
Margin="{StaticResource Margin8}" Margin="{StaticResource Margin8}"

View file

@ -1,4 +1,4 @@
<reactiveui:ReactiveUserControl <reactiveui:ReactiveUserControl
x:Class="v2rayN.Views.CheckUpdateView" x:Class="v2rayN.Views.CheckUpdateView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -39,15 +39,6 @@
Content="{x:Static resx:ResUI.menuCheckUpdate}" Content="{x:Static resx:ResUI.menuCheckUpdate}"
IsDefault="True" IsDefault="True"
Style="{StaticResource DefButton}" /> Style="{StaticResource DefButton}" />
<Button
Width="100"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Right"
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
Content="{x:Static resx:ResUI.menuClose}"
IsCancel="True"
Style="{StaticResource DefButton}" />
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>

View file

@ -32,6 +32,7 @@
<materialDesign:DialogHost <materialDesign:DialogHost
materialDesign:TransitionAssist.DisableTransitions="True" materialDesign:TransitionAssist.DisableTransitions="True"
CloseOnClickAway="True"
Identifier="RootDialog" Identifier="RootDialog"
SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}" SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}"
Style="{StaticResource MaterialDesignEmbeddedDialogHost}"> Style="{StaticResource MaterialDesignEmbeddedDialogHost}">
@ -231,23 +232,6 @@
</MenuItem> </MenuItem>
</Menu> </Menu>
<Separator /> <Separator />
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem
x:Name="menuReload"
Padding="{StaticResource MarginLeftRight8}"
AutomationProperties.Name="{x:Static resx:ResUI.menuReload}">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="Reload" />
<TextBlock Text="{x:Static resx:ResUI.menuReload}" />
</StackPanel>
</MenuItem.Header>
</MenuItem>
</Menu>
<Separator />
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}"> <Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem <MenuItem
x:Name="menuHelp" x:Name="menuHelp"
@ -267,6 +251,23 @@
</MenuItem> </MenuItem>
</Menu> </Menu>
<Separator /> <Separator />
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem
x:Name="menuReload"
Padding="{StaticResource MarginLeftRight8}"
AutomationProperties.Name="{x:Static resx:ResUI.menuReload}">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="Reload" />
<TextBlock Text="{x:Static resx:ResUI.menuReload}" />
</StackPanel>
</MenuItem.Header>
</MenuItem>
</Menu>
<Separator />
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}"> <Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
<MenuItem <MenuItem
x:Name="menuPromotion" x:Name="menuPromotion"

View file

@ -15,18 +15,7 @@
<sys:Double x:Key="QrcodeWidth">400</sys:Double> <sys:Double x:Key="QrcodeWidth">400</sys:Double>
</UserControl.Resources> </UserControl.Resources>
<DockPanel Margin="{StaticResource Margin8}"> <StackPanel Margin="{StaticResource Margin8}">
<StackPanel Margin="{StaticResource Margin8}" DockPanel.Dock="Bottom">
<Button
Width="100"
HorizontalAlignment="Right"
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
Content="{x:Static resx:ResUI.menuClose}"
IsCancel="True"
IsDefault="True"
Style="{StaticResource DefButton}" />
</StackPanel>
<Grid Margin="{StaticResource Margin8}"> <Grid Margin="{StaticResource Margin8}">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
@ -51,5 +40,5 @@
TextWrapping="Wrap" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" /> VerticalScrollBarVisibility="Auto" />
</Grid> </Grid>
</DockPanel> </StackPanel>
</UserControl> </UserControl>

View file

@ -20,6 +20,7 @@
mc:Ignorable="d"> mc:Ignorable="d">
<materialDesign:DialogHost <materialDesign:DialogHost
materialDesign:TransitionAssist.DisableTransitions="True" materialDesign:TransitionAssist.DisableTransitions="True"
CloseOnClickAway="True"
Identifier="SubDialog" Identifier="SubDialog"
Style="{StaticResource MaterialDesignEmbeddedDialogHost}"> Style="{StaticResource MaterialDesignEmbeddedDialogHost}">
<DockPanel> <DockPanel>