This commit is contained in:
DHR60 2025-11-02 12:38:21 +08:00
parent c14a0e33b7
commit 640edb5eb2
13 changed files with 176 additions and 77 deletions

View file

@ -87,6 +87,24 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Certificate not set 的本地化字符串。
/// </summary>
public static string CertNotSet {
get {
return ResourceManager.GetString("CertNotSet", resourceCulture);
}
}
/// <summary>
/// 查找类似 Certificate set 的本地化字符串。
/// </summary>
public static string CertSet {
get {
return ResourceManager.GetString("CertSet", resourceCulture);
}
}
/// <summary>
/// 查找类似 Please check the Configuration settings first. 的本地化字符串。
/// </summary>

View file

@ -1618,4 +1618,10 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="ServerNameMustBeValidDomain" xml:space="preserve">
<value>Please set a valid domain</value>
</data>
<data name="CertNotSet" xml:space="preserve">
<value>Certificate not set</value>
</data>
<data name="CertSet" xml:space="preserve">
<value>Certificate set</value>
</data>
</root>

View file

@ -1615,4 +1615,10 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="ServerNameMustBeValidDomain" xml:space="preserve">
<value>Please set a valid domain</value>
</data>
<data name="CertNotSet" xml:space="preserve">
<value>Certificate not set</value>
</data>
<data name="CertSet" xml:space="preserve">
<value>Certificate set</value>
</data>
</root>

View file

@ -1618,4 +1618,10 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="ServerNameMustBeValidDomain" xml:space="preserve">
<value>Please set a valid domain</value>
</data>
<data name="CertNotSet" xml:space="preserve">
<value>Certificate not set</value>
</data>
<data name="CertSet" xml:space="preserve">
<value>Certificate set</value>
</data>
</root>

View file

@ -1618,4 +1618,10 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="ServerNameMustBeValidDomain" xml:space="preserve">
<value>Please set a valid domain</value>
</data>
<data name="CertNotSet" xml:space="preserve">
<value>Certificate not set</value>
</data>
<data name="CertSet" xml:space="preserve">
<value>Certificate set</value>
</data>
</root>

View file

@ -1618,4 +1618,10 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="ServerNameMustBeValidDomain" xml:space="preserve">
<value>Please set a valid domain</value>
</data>
<data name="CertNotSet" xml:space="preserve">
<value>Certificate not set</value>
</data>
<data name="CertSet" xml:space="preserve">
<value>Certificate set</value>
</data>
</root>

View file

@ -1615,4 +1615,10 @@
<data name="ServerNameMustBeValidDomain" xml:space="preserve">
<value>请设置有效的域名</value>
</data>
<data name="CertNotSet" xml:space="preserve">
<value>证书未设置</value>
</data>
<data name="CertSet" xml:space="preserve">
<value>证书已设置</value>
</data>
</root>

View file

@ -1615,4 +1615,10 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="ServerNameMustBeValidDomain" xml:space="preserve">
<value>Please set a valid domain</value>
</data>
<data name="CertNotSet" xml:space="preserve">
<value>Certificate not set</value>
</data>
<data name="CertSet" xml:space="preserve">
<value>Certificate set</value>
</data>
</root>

View file

@ -2,6 +2,8 @@ namespace ServiceLib.ViewModels;
public class AddServerViewModel : MyReactiveObject
{
private string _certError = string.Empty;
[Reactive]
public ProfileItem SelectedSource { get; set; }
@ -11,6 +13,9 @@ public class AddServerViewModel : MyReactiveObject
[Reactive]
public string Cert { get; set; }
[Reactive]
public string CertTip { get; set; }
public ReactiveCommand<Unit, Unit> FetchCertCmd { get; }
public ReactiveCommand<Unit, Unit> FetchCertChainCmd { get; }
public ReactiveCommand<Unit, Unit> SaveCmd { get; }
@ -33,6 +38,9 @@ public class AddServerViewModel : MyReactiveObject
await SaveServerAsync();
});
this.WhenAnyValue(x => x.Cert)
.Subscribe(_ => UpdateCertTip());
if (profileItem.IndexId.IsNullOrEmpty())
{
profileItem.Network = Global.DefaultNetwork;
@ -104,6 +112,13 @@ public class AddServerViewModel : MyReactiveObject
}
}
private void UpdateCertTip()
{
CertTip = _certError.IsNullOrEmpty()
? (Cert.IsNullOrEmpty() ? ResUI.CertNotSet : ResUI.CertSet)
: _certError;
}
private async Task FetchCert()
{
if (SelectedSource.StreamSecurity != Global.StreamSecurity)
@ -122,7 +137,9 @@ public class AddServerViewModel : MyReactiveObject
}
if (!Utils.IsDomain(serverName))
{
NoticeManager.Instance.Enqueue(ResUI.ServerNameMustBeValidDomain);
_certError = ResUI.ServerNameMustBeValidDomain;
UpdateCertTip();
_certError = string.Empty;
return;
}
if (SelectedSource.Port > 0)
@ -150,7 +167,9 @@ public class AddServerViewModel : MyReactiveObject
}
if (!Utils.IsDomain(serverName))
{
NoticeManager.Instance.Enqueue(ResUI.ServerNameMustBeValidDomain);
_certError = ResUI.ServerNameMustBeValidDomain;
UpdateCertTip();
_certError = string.Empty;
return;
}
if (SelectedSource.Port > 0)

View file

@ -775,50 +775,59 @@
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbCertPinning}" />
<Button
<StackPanel
Grid.Row="5"
Grid.Column="1"
Margin="{StaticResource MarginLr8}"
HorizontalAlignment="Left"
Classes="IconButton">
<Button.Content>
<PathIcon Data="{StaticResource SemiIconMore}">
<PathIcon.RenderTransform>
<RotateTransform Angle="90" />
</PathIcon.RenderTransform>
</PathIcon>
</Button.Content>
<Button.Flyout>
<Flyout>
<StackPanel>
<TextBlock
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbCertPinningTips}" />
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<Button
x:Name="btnFetchCert"
VerticalAlignment="Center"
Orientation="Horizontal">
<TextBlock
x:Name="labCertPinning"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center" />
<Button
Margin="{StaticResource MarginLr4}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Classes="IconButton">
<Button.Content>
<PathIcon Data="{StaticResource SemiIconMore}">
<PathIcon.RenderTransform>
<RotateTransform Angle="90" />
</PathIcon.RenderTransform>
</PathIcon>
</Button.Content>
<Button.Flyout>
<Flyout>
<StackPanel>
<TextBlock
Margin="{StaticResource Margin4}"
Content="{x:Static resx:ResUI.TbFetchCert}" />
<Button
x:Name="btnFetchCertChain"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbCertPinningTips}" />
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<Button
x:Name="btnFetchCert"
Margin="{StaticResource Margin4}"
Content="{x:Static resx:ResUI.TbFetchCert}" />
<Button
x:Name="btnFetchCertChain"
Margin="{StaticResource Margin4}"
Content="{x:Static resx:ResUI.TbFetchCertChain}" />
</StackPanel>
<TextBox
x:Name="txtCert"
Width="400"
MinHeight="100"
Margin="{StaticResource Margin4}"
Content="{x:Static resx:ResUI.TbFetchCertChain}" />
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Classes="TextArea"
MinLines="6"
TextWrapping="Wrap" />
</StackPanel>
<TextBox
x:Name="txtCert"
Width="400"
MinHeight="100"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Classes="TextArea"
MinLines="6"
TextWrapping="Wrap" />
</StackPanel>
</Flyout>
</Button.Flyout>
</Button>
</Flyout>
</Button.Flyout>
</Button>
</StackPanel>
</Grid>
<Grid
x:Name="gridRealityMore"

View file

@ -185,6 +185,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.Alpn, v => v.cmbAlpn.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CertTip, v => v.labCertPinning.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Cert, v => v.txtCert.Text).DisposeWith(disposables);
//reality
this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables);

View file

@ -1004,45 +1004,54 @@
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbCertPinning}" />
<materialDesign:PopupBox
<StackPanel
Grid.Row="5"
Grid.Column="1"
HorizontalAlignment="Left"
StaysOpen="True"
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
<StackPanel>
<TextBlock
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbCertPinningTips}"
TextWrapping="Wrap" />
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<Button
x:Name="btnFetchCert"
Width="100"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbFetchCert}"
Style="{StaticResource DefButton}" />
<Button
x:Name="btnFetchCertChain"
Width="100"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbFetchCertChain}"
Style="{StaticResource DefButton}" />
VerticalAlignment="Center"
Orientation="Horizontal">
<TextBlock
x:Name="labCertPinning"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}" />
<materialDesign:PopupBox
HorizontalAlignment="Left"
VerticalAlignment="Center"
StaysOpen="True"
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
<StackPanel>
<TextBlock
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbCertPinningTips}"
TextWrapping="Wrap" />
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<Button
x:Name="btnFetchCert"
Width="100"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbFetchCert}"
Style="{StaticResource DefButton}" />
<Button
x:Name="btnFetchCertChain"
Width="100"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbFetchCertChain}"
Style="{StaticResource DefButton}" />
</StackPanel>
<TextBox
x:Name="txtCert"
Width="400"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
AcceptsReturn="True"
MinLines="6"
Style="{StaticResource MyOutlinedTextBox}"
TextWrapping="Wrap" />
</StackPanel>
<TextBox
x:Name="txtCert"
Width="400"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
AcceptsReturn="True"
MinLines="6"
Style="{StaticResource MyOutlinedTextBox}"
TextWrapping="Wrap" />
</StackPanel>
</materialDesign:PopupBox>
</materialDesign:PopupBox>
</StackPanel>
</Grid>
<Grid

View file

@ -180,6 +180,7 @@ public partial class AddServerWindow
this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource.Alpn, v => v.cmbAlpn.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CertTip, v => v.labCertPinning.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Cert, v => v.txtCert.Text).DisposeWith(disposables);
//reality
this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables);