From 41cfb8c8f4fce3022d237bfa5c3064c878e349ca Mon Sep 17 00:00:00 2001 From: cheri Date: Mon, 22 Jun 2026 08:25:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BD=91=E7=BB=9C=E4=BB=A3?= =?UTF-8?q?=E7=90=86=E8=AE=BE=E7=BD=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 支持HTTP和SOCKS5代理配置 - 在设置界面添加代理启用开关、类型选择、地址和端口输入 - 添加代理测试功能,显示延迟结果 - 反馈中心正确显示当前代理状态 --- .../ServiceCollectionExtension.HttpClient.cs | 4 +- .../Core/IO/Http/Proxy/HutaoWebProxy.cs | 136 ++++++++++++++++++ .../Snap.Hutao/Core/Setting/SettingKeys.cs | 6 + .../Snap.Hutao/Model/Intrinsic/ProxyType.cs | 20 +++ .../Snap.Hutao/Resource/Localization/SH.resx | 57 ++++++++ .../Snap.Hutao/Service/AppOptions.cs | 15 ++ .../UI/Xaml/View/Page/SettingPage.xaml | 67 +++++++++ .../ViewModel/Feedback/FeedbackViewModel.cs | 2 +- .../Setting/SettingProxyViewModel.cs | 96 +++++++++++++ .../ViewModel/Setting/SettingViewModel.cs | 4 +- 10 files changed, 404 insertions(+), 3 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Proxy/HutaoWebProxy.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ProxyType.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingProxyViewModel.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/ServiceCollectionExtension.HttpClient.cs b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/ServiceCollectionExtension.HttpClient.cs index 2c60097..7bdc94c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/ServiceCollectionExtension.HttpClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/ServiceCollectionExtension.HttpClient.cs @@ -4,6 +4,7 @@ using JetBrains.Annotations; using Snap.Hutao.Core.IO.Http; using Snap.Hutao.Core.IO.Http.Proxy; +using Snap.Hutao.Service; using Snap.Hutao.Service.Game.Package.Advanced; using Snap.Hutao.Web.Hoyolab; using Snap.Hutao.Win32; @@ -36,10 +37,11 @@ internal static partial class ServiceCollectionExtension { SocketsHttpHandler typedHandler = Unsafe.As(handler); typedHandler.UseProxy = true; - typedHandler.Proxy = HttpProxyUsingSystemProxy.Instance; + typedHandler.Proxy = provider.GetRequiredService(); }) .AddHttpMessageHandler(); }) + .AddSingleton(sp => new HutaoWebProxy(sp.GetRequiredService(), HttpProxyUsingSystemProxy.Instance)) .AddHttpClients(); services diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Proxy/HutaoWebProxy.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Proxy/HutaoWebProxy.cs new file mode 100644 index 0000000..d89153b --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Proxy/HutaoWebProxy.cs @@ -0,0 +1,136 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Model.Intrinsic; +using Snap.Hutao.Service; +using System.Net; +using System.Net.Http; + +namespace Snap.Hutao.Core.IO.Http.Proxy; + +internal sealed class HutaoWebProxy : IWebProxy +{ + private readonly AppOptions appOptions; + private readonly HttpProxyUsingSystemProxy systemProxy; + + public HutaoWebProxy(AppOptions appOptions, HttpProxyUsingSystemProxy systemProxy) + { + this.appOptions = appOptions; + this.systemProxy = systemProxy; + } + + public ICredentials? Credentials + { + get => InnerProxy.Credentials; + set => InnerProxy.Credentials = value; + } + + public string DisplayProxyUri + { + get + { + if (!appOptions.ProxyEnabled.Value) + { + return systemProxy.DisplayProxyUri; + } + + return appOptions.ProxyType.Value switch + { + ProxyType.SystemProxy => systemProxy.DisplayProxyUri, + ProxyType.Http => string.IsNullOrEmpty(appOptions.ProxyAddress.Value) + ? systemProxy.DisplayProxyUri + : $"http://{appOptions.ProxyAddress.Value}:{appOptions.ProxyPort.Value}", + ProxyType.Socks5 => string.IsNullOrEmpty(appOptions.ProxyAddress.Value) + ? systemProxy.DisplayProxyUri + : $"socks5://{appOptions.ProxyAddress.Value}:{appOptions.ProxyPort.Value}", + ProxyType.None => systemProxy.DisplayProxyUri, + _ => systemProxy.DisplayProxyUri, + }; + } + } + + private IWebProxy InnerProxy + { + get + { + if (!appOptions.ProxyEnabled.Value) + { + return systemProxy; + } + + return appOptions.ProxyType.Value switch + { + ProxyType.SystemProxy => systemProxy, + ProxyType.Http => CreateHttpProxy(), + ProxyType.Socks5 => CreateSocks5Proxy(), + ProxyType.None => systemProxy, + _ => systemProxy, + }; + } + } + + public Uri? GetProxy(Uri destination) + { + return InnerProxy.GetProxy(destination); + } + + public bool IsBypassed(Uri host) + { + return InnerProxy.IsBypassed(host); + } + + private IWebProxy CreateHttpProxy() + { + string address = appOptions.ProxyAddress.Value; + int port = appOptions.ProxyPort.Value; + + if (string.IsNullOrEmpty(address)) + { + return systemProxy; + } + + WebProxy webProxy = new() + { + Address = new Uri($"http://{address}:{port}"), + }; + + return webProxy; + } + + private IWebProxy CreateSocks5Proxy() + { + string address = appOptions.ProxyAddress.Value; + int port = appOptions.ProxyPort.Value; + + if (string.IsNullOrEmpty(address)) + { + return systemProxy; + } + + return new Socks5WebProxy(address, port); + } +} + +internal sealed class Socks5WebProxy : IWebProxy +{ + private readonly string address; + private readonly int port; + + public Socks5WebProxy(string address, int port) + { + this.address = address; + this.port = port; + } + + public ICredentials? Credentials { get; set; } + + public Uri? GetProxy(Uri destination) + { + return new Uri($"socks5://{address}:{port}"); + } + + public bool IsBypassed(Uri host) + { + return false; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs b/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs index 03c48ee..02a09a6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs @@ -152,4 +152,10 @@ internal static class SettingKeys public const string CompactWebView2WindowInactiveOpacity = "Snap::Hutao::Web::WebView::Compact::InactiveOpacity"; public const string CompactWebView2WindowPreviousSourceUrl = "Snap::Hutao::Web::WebView::Compact::PreviousSourceUrl"; public const string WebView2VideoFastForwardOrRewindSeconds = "Snap::Hutao::Web::WebView::Video::FastForwardOrRewind::Seconds"; + + // Proxy + public const string ProxyType = "Snap::Hutao::Web::Proxy::Type"; + public const string ProxyAddress = "Snap::Hutao::Web::Proxy::Address"; + public const string ProxyPort = "Snap::Hutao::Web::Proxy::Port"; + public const string ProxyEnabled = "Snap::Hutao::Web::Proxy::Enabled"; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ProxyType.cs b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ProxyType.cs new file mode 100644 index 0000000..d32000e --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ProxyType.cs @@ -0,0 +1,20 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Model.Intrinsic; + +[ExtendedEnum] +internal enum ProxyType +{ + [LocalizationKey(nameof(SH.ServiceProxyTypeNone))] + None = 0, + + [LocalizationKey(nameof(SH.ServiceProxyTypeSystemProxy))] + SystemProxy = 1, + + [LocalizationKey(nameof(SH.ServiceProxyTypeHttp))] + Http = 2, + + [LocalizationKey(nameof(SH.ServiceProxyTypeSocks5))] + Socks5 = 3, +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index b0fc331..b656ffd 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -875,6 +875,18 @@ 无背景图片 + + 无代理 + + + 系统代理 + + + HTTP 代理 + + + SOCKS5 代理 + 退出胡桃 @@ -2255,6 +2267,24 @@ 删除转换服务器游戏客户端缓存 + + 代理设置已保存 + + + 正在测试代理连接... + + + 可用 [{0}ms] + + + 不可用 + + + 测试 + + + 保存 + 已使用磁盘空间:{0} @@ -3330,6 +3360,33 @@ 无感验证 + + 网络代理 + + + 启用自定义代理设置 + + + 启用代理 + + + 选择代理类型 + + + 代理类型 + + + 代理服务器地址 + + + 代理地址 + + + 代理服务器端口 + + + 代理端口 + 选择想要获取公告的游戏服务器 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs index b966142..b6530c1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs @@ -5,6 +5,7 @@ using Microsoft.UI.Xaml; using Snap.Hutao.Core.Property; using Snap.Hutao.Core.Setting; using Snap.Hutao.Model; +using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Service.Abstraction; using Snap.Hutao.Service.BackgroundImage; using Snap.Hutao.UI.Xaml.Media.Backdrop; @@ -49,6 +50,8 @@ internal sealed partial class AppOptions : DbStoreOptions public ImmutableArray> BridgeShareSaveTypes { get; } = ImmutableCollectionsNameValue.FromEnum(type => type.GetLocalizedDescription(SH.ResourceManager, CultureInfo.CurrentCulture) ?? string.Empty); + public ImmutableArray> ProxyTypes { get; } = ImmutableCollectionsNameValue.FromEnum(static @enum => @enum.GetLocalizedDescription(SH.ResourceManager, CultureInfo.CurrentCulture) ?? string.Empty); + public ImmutableArray> LastWindowCloseBehaviors { get; } = ImmutableCollectionsNameValue.FromEnum(static @enum => @enum.GetLocalizedDescription(SH.ResourceManager, CultureInfo.CurrentCulture) ?? string.Empty); [field: MaybeNull] @@ -83,4 +86,16 @@ internal sealed partial class AppOptions : DbStoreOptions [field: MaybeNull] public IObservableProperty LastWindowCloseBehavior { get => field ??= CreateProperty(SettingKeys.LastWindowCloseBehavior, Service.LastWindowCloseBehavior.EnsureNotifyIconCreated); } + + [field: MaybeNull] + public IObservableProperty ProxyType { get => field ??= CreateProperty(SettingKeys.ProxyType, Model.Intrinsic.ProxyType.SystemProxy); } + + [field: MaybeNull] + public IObservableProperty ProxyAddress { get => field ??= CreateProperty(SettingKeys.ProxyAddress, string.Empty); } + + [field: MaybeNull] + public IObservableProperty ProxyPort { get => field ??= CreateProperty(SettingKeys.ProxyPort, 1080); } + + [field: MaybeNull] + public IObservableProperty ProxyEnabled { get => field ??= CreateProperty(SettingKeys.ProxyEnabled, false); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/SettingPage.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/SettingPage.xaml index 9464422..eba6b88 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/SettingPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/SettingPage.xaml @@ -210,6 +210,73 @@ + + + + + + + + + + + + + + + + + + + + + +