From eed98bf8d5091e8d0f706d9d4370f90214aea85d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Sun, 1 Jun 2025 17:22:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E5=A4=9A=E6=9B=B4=E6=96=B0=E6=B8=A0?= =?UTF-8?q?=E9=81=93=E7=9A=84UI=E6=94=B9=E9=80=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BetterGenshinImpact.sln.DotSettings | 4 +- .../Assets/Strings/md2html.html | 6 +- BetterGenshinImpact/Model/UpdateOption.cs | 11 ++ .../Model/Mirrorchan/LatestResponse.cs | 117 ++++++++++++++++ BetterGenshinImpact/Service/UpdateService.cs | 132 ++++++++++++++++-- .../View/Pages/CommonSettingsPage.xaml | 31 +++- .../View/Windows/CheckUpdateWindow.xaml | 16 +-- .../View/Windows/CheckUpdateWindow.xaml.cs | 60 +++++++- .../Pages/CommonSettingsPageViewModel.cs | 28 ++++ 9 files changed, 372 insertions(+), 33 deletions(-) create mode 100644 BetterGenshinImpact/Service/Model/Mirrorchan/LatestResponse.cs diff --git a/BetterGenshinImpact.sln.DotSettings b/BetterGenshinImpact.sln.DotSettings index 46e57701..0cf4b727 100644 --- a/BetterGenshinImpact.sln.DotSettings +++ b/BetterGenshinImpact.sln.DotSettings @@ -1,2 +1,4 @@  - True \ No newline at end of file + True + True + True \ No newline at end of file diff --git a/BetterGenshinImpact/Assets/Strings/md2html.html b/BetterGenshinImpact/Assets/Strings/md2html.html index f559099d..429babf3 100644 --- a/BetterGenshinImpact/Assets/Strings/md2html.html +++ b/BetterGenshinImpact/Assets/Strings/md2html.html @@ -18,14 +18,10 @@ ::-webkit-scrollbar-thumb:hover { background: #555; } - .body { - background-color: #202020; - color: #e6edf3; - } .markdown-body { margin: 0; padding: 8px; - background-color: #202020; + background-color: #202020 !important; height: 100% } * { diff --git a/BetterGenshinImpact/Model/UpdateOption.cs b/BetterGenshinImpact/Model/UpdateOption.cs index eb68bf53..ba899fa7 100644 --- a/BetterGenshinImpact/Model/UpdateOption.cs +++ b/BetterGenshinImpact/Model/UpdateOption.cs @@ -3,6 +3,10 @@ public sealed class UpdateOption { public UpdateTrigger Trigger { get; set; } = default; + + public UpdateChannel Channel { get; set; } = UpdateChannel.Stable; + + public string? MirrorChanCdk { get; set; } } public enum UpdateTrigger @@ -10,3 +14,10 @@ public enum UpdateTrigger Auto, Manual, } + + +public enum UpdateChannel +{ + Stable, + Alpha, +} \ No newline at end of file diff --git a/BetterGenshinImpact/Service/Model/Mirrorchan/LatestResponse.cs b/BetterGenshinImpact/Service/Model/Mirrorchan/LatestResponse.cs new file mode 100644 index 00000000..88d4ec11 --- /dev/null +++ b/BetterGenshinImpact/Service/Model/Mirrorchan/LatestResponse.cs @@ -0,0 +1,117 @@ +using System.Text.Json.Serialization; + +namespace BetterGenshinImpact.Service.Model.Mirrorchan; + +#nullable enable +#pragma warning disable CS8618 +#pragma warning disable CS8601 +#pragma warning disable CS8603 +public partial class LatestResponse +{ + /// + /// 响应代码,https://github.com/MirrorChyan/docs/blob/main/ErrorCode.md + /// + [JsonPropertyName("code")] + public long Code { get; set; } + + /// + /// 响应数据 + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("data")] + public Data Data { get; set; } + + /// + /// 响应信息 + /// + [JsonPropertyName("msg")] + public string Msg { get; set; } +} + +/// +/// 响应数据 +/// +public partial class Data +{ + /// + /// 更新包架构 + /// + [JsonPropertyName("arch")] + public string Arch { get; set; } + + /// + /// CDK过期时间戳 + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("cdk_expired_time")] + public double? CdkExpiredTime { get; set; } + + /// + /// 更新频道,stable | beta | alpha + /// + [JsonPropertyName("channel")] + public string Channel { get; set; } + + /// + /// 自定义数据 + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("custom_data")] + public string CustomData { get; set; } + + /// + /// 文件大小 + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("filesize")] + public long? Filesize { get; set; } + + /// + /// 更新包系统 + /// + [JsonPropertyName("os")] + public string Os { get; set; } + + /// + /// 发版日志 + /// + [JsonPropertyName("release_note")] + public string ReleaseNote { get; set; } + + /// + /// sha256 + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("sha256")] + public string Sha256 { get; set; } + + /// + /// 更新包类型,incremental | full + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("update_type")] + public string UpdateType { get; set; } + + /// + /// 下载地址 + /// + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("url")] + public string Url { get; set; } + + /// + /// 资源版本名称 + /// + [JsonPropertyName("version_name")] + public string VersionName { get; set; } + + /// + /// 资源版本号仅内部使用 + /// + [JsonPropertyName("version_number")] + public long VersionNumber { get; set; } +} + +#pragma warning restore CS8618 +#pragma warning restore CS8601 +#pragma warning restore CS8603 \ No newline at end of file diff --git a/BetterGenshinImpact/Service/UpdateService.cs b/BetterGenshinImpact/Service/UpdateService.cs index e5cf9d9c..9a473db8 100644 --- a/BetterGenshinImpact/Service/UpdateService.cs +++ b/BetterGenshinImpact/Service/UpdateService.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Json; @@ -18,6 +19,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; +using BetterGenshinImpact.Service.Model.Mirrorchan; +using Wpf.Ui.Violeta.Controls; namespace BetterGenshinImpact.Service; @@ -37,7 +40,7 @@ public class UpdateService : IUpdateService _configService = configService; Config = _configService.Get(); } - + /// /// Please call me in main thread @@ -50,13 +53,13 @@ public class UpdateService : IUpdateService #if DEBUG && false return; #endif - string newVersion = await GetLatestVersionAsync(); + string newVersion = await GetLatestVersionAsync(option); if (string.IsNullOrWhiteSpace(newVersion)) { return; } - + // ---- 如果是调试模式且手动的检查更新的情况下,强制打开更新窗口 ----- // 方便调试窗口 if (RuntimeHelper.IsDebuggerAttached && option.Trigger == UpdateTrigger.Manual) @@ -72,7 +75,7 @@ public class UpdateService : IUpdateService { await MessageBox.InformationAsync("当前已是最新版本!"); } - + return; } @@ -87,7 +90,8 @@ public class UpdateService : IUpdateService } catch (Exception e) { - Debug.WriteLine("获取最新版本信息失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); + Debug.WriteLine("获取最新版本信息失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + + Environment.NewLine + e.Message); _logger.LogWarning("获取 BetterGI 最新版本信息失败"); } } @@ -122,12 +126,12 @@ public class UpdateService : IUpdateService await MessageBox.ErrorAsync("更新程序不存在,请选择其他更新方式!"); return; } + // 启动 Process.Start(updaterExePath, "-I"); - + // 退出程序 Application.Current.Shutdown(); - } break; @@ -144,11 +148,112 @@ public class UpdateService : IUpdateService } }; - win.NavigateToHtml(await GetReleaseMarkdownHtmlAsync()); + if (option.Channel == UpdateChannel.Stable) + { + win.NavigateToHtml(await GetReleaseMarkdownHtmlAsync()); + } + win.ShowDialog(); } - private async Task GetLatestVersionAsync() + private async Task GetLatestVersionAsync(UpdateOption option) + { + if (option.Channel == UpdateChannel.Stable) + { + return await UpdateFromOss(); + } + else + { + return await UpdateFromMirrorChan(option); + } + } + + /// + /// 文档 + /// https://apifox.com/apidoc/shared/ffdc8453-597d-4ba6-bd3c-5e375c10c789 + /// + /// + /// + private async Task UpdateFromMirrorChan(UpdateOption option) + { + if (string.IsNullOrWhiteSpace(option.MirrorChanCdk)) + { + Toast.Warning("Mirror酱源更新检查失败,未设置CDK"); + return string.Empty; + } + + try + { + const string url = "https://mirrorchyan.com/api/resources/BGI/latest"; + var queryParams = new Dictionary + { + { "cdk", option.MirrorChanCdk }, + { "user_agent", "BetterGI" }, + { "os", "win" }, + { "arch", "x64" }, + { "channel", "alpha" } + }; + + using var httpClient = new HttpClient(); + + var finalUrl = $"{url}?{string.Join("&", queryParams.Select(x => $"{x.Key}={x.Value}"))}"; + var response = await httpClient.GetFromJsonAsync(finalUrl); + + if (response != null) + { + if (response.Code == 0) + { + return response.Data.VersionName; + } + else if (response.Code < 0) + { + Toast.Error( + $"Mirror酱源更新检查失败,意料之外的严重错误,请及时联系 Mirror 酱的技术支持处理\n,错误代码:{response.Code},错误信息:{response.Msg}"); + return string.Empty; + } + else + { + ToastError(response); + } + } + } + catch (Exception e) + { + _logger.LogDebug(e, "Mirror源更新检查失败"); + } + + return string.Empty; + } + + private static void ToastError(LatestResponse response) + { + if (response.Code == 7001) + { + Toast.Warning("Mirror酱 CDK 已过期,请重新获取CDK"); + } + else if (response.Code == 7002) + { + Toast.Warning("Mirror酱 CDK 错误!"); + } + else if (response.Code == 7003) + { + Toast.Warning("Mirror酱 CDK 今日下载次数已达上限"); + } + else if (response.Code == 7004) + { + Toast.Warning("Mirror酱 CDK 类型和待下载的资源不匹配"); + } + else if (response.Code == 7005) + { + Toast.Warning("Mirror酱 CDK 已被封禁"); + } + else + { + Toast.Warning($"Mirror酱源更新检查失败,错误信息:{response.Msg}"); + } + } + + private async Task UpdateFromOss() { try { @@ -181,7 +286,9 @@ public class UpdateService : IUpdateService { using HttpClient httpClient = new(); httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); - string jsonString = await httpClient.GetStringAsync("https://api.github.com/repos/babalae/better-genshin-impact/releases/latest"); + string jsonString = + await httpClient.GetStringAsync( + "https://api.github.com/repos/babalae/better-genshin-impact/releases/latest"); var jsonDict = JsonConvert.DeserializeObject>(jsonString); if (jsonDict != null) @@ -191,7 +298,8 @@ public class UpdateService : IUpdateService string md = $"# {name}{new string('\n', 2)}{body}"; md = WebUtility.HtmlEncode(md); - string md2html = ResourceHelper.GetString($"pack://application:,,,/Assets/Strings/md2html.html", Encoding.UTF8); + string md2html = ResourceHelper.GetString($"pack://application:,,,/Assets/Strings/md2html.html", + Encoding.UTF8); var html = md2html.Replace("{{content}}", md); return html; @@ -240,4 +348,4 @@ public class UpdateService : IUpdateService """; } -} +} \ No newline at end of file diff --git a/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml b/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml index adc3ea37..fcbcd153 100644 --- a/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml +++ b/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml @@ -1078,7 +1078,7 @@ Grid.RowSpan="2" Grid.Column="1" Margin="0,0,20,0" - Command="{Binding OpenKeyBindingsWindowCommand}" + Command="{Binding CheckUpdateCommand}" Content="检查更新" /> @@ -1099,15 +1099,40 @@ + + + + + + + + + + + + + diff --git a/BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml b/BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml index 78a93e6f..8997aaf0 100644 --- a/BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml +++ b/BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml @@ -47,12 +47,12 @@ @@ -61,7 +61,7 @@ Appearance="Success" Icon="{ui:SymbolIcon ArrowDownload24}" Content="立即更新" - Command="{Binding UpdateCommand}" /> + Command="{Binding UpdateFromSteambirdCommand}" /> @@ -87,14 +87,14 @@ + Content="立即更新" + Command="{Binding UpdateFromMirrorchanCommand}" /> - + ? UserInteraction = null!; - [ObservableProperty] - private bool showUpdateStatus = false; + [ObservableProperty] private bool showUpdateStatus = false; - [ObservableProperty] - private string updateStatusMessage = string.Empty; + [ObservableProperty] private string updateStatusMessage = string.Empty; + + private UpdateOption _option; public CheckUpdateWindow(UpdateOption option) { + _option = option ?? throw new ArgumentNullException(nameof(option)); DataContext = this; InitializeComponent(); @@ -30,6 +34,11 @@ public partial class CheckUpdateWindow : FluentWindow IgnoreButton.Visibility = Visibility.Collapsed; } + if (option.Channel == UpdateChannel.Alpha) + { + WebpagePanel.Visibility = Visibility.Collapsed; + } + Closing += OnClosing; } @@ -73,6 +82,49 @@ public partial class CheckUpdateWindow : FluentWindow } } + + [RelayCommand] + private async Task UpdateFromSteambirdAsync() + { + await RunUpdaterAsync("-I"); + } + + [RelayCommand] + private async Task UpdateFromMirrorchanAsync() + { + if (_option.Channel == UpdateChannel.Stable) + { + await RunUpdaterAsync("--source mirrorc"); + } + else + { + await RunUpdaterAsync("--source mirrorc-alpha"); + } + } + + /// + /// --source mirrorc + /// --source mirrorc-alpha + /// --source github + /// --dfs-extras {"hutao-token": "...."} + /// + private async Task RunUpdaterAsync(string parameters) + { + // 唤起更新程序 + string updaterExePath = Global.Absolute("BetterGI.update.exe"); + if (!File.Exists(updaterExePath)) + { + await MessageBox.ErrorAsync("更新程序不存在,请选择其他更新方式!"); + return; + } + + // 启动 + Process.Start(updaterExePath, parameters); + + // 退出程序 + Application.Current.Shutdown(); + } + [RelayCommand] private async Task IgnoreAsync() { diff --git a/BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs index fb41c4c2..8ed829d0 100644 --- a/BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs @@ -9,6 +9,7 @@ using System.IO.Compression; using System.Linq; using System.Threading.Tasks; using System.Windows; +using Windows.System; using BetterGenshinImpact.Core.Config; using BetterGenshinImpact.Core.Recognition.OCR; using BetterGenshinImpact.Core.Script; @@ -16,6 +17,7 @@ using BetterGenshinImpact.GameTask; using BetterGenshinImpact.GameTask.AutoTrackPath; using BetterGenshinImpact.GameTask.Common.Element.Assets; using BetterGenshinImpact.Helpers; +using BetterGenshinImpact.Model; using BetterGenshinImpact.Service.Interface; using BetterGenshinImpact.Service.Notification; using BetterGenshinImpact.View.Converters; @@ -260,4 +262,30 @@ public partial class CommonSettingsPageViewModel : ViewModel { await OcrFactory.ChangeCulture(type.Key); } + + [RelayCommand] + private async Task CheckUpdateAsync() + { + await App.GetService()!.CheckUpdateAsync(new UpdateOption + { + Trigger = UpdateTrigger.Manual, + Channel = UpdateChannel.Stable + }); + } + + [RelayCommand] + private async Task CheckUpdateAlphaAsync() + { + await App.GetService()!.CheckUpdateAsync(new UpdateOption + { + Trigger = UpdateTrigger.Manual, + Channel = UpdateChannel.Alpha + }); + } + + [RelayCommand] + private async Task GotoGithubActionAsync() + { + await Launcher.LaunchUriAsync(new Uri("https://github.com/babalae/better-genshin-impact/actions/workflows/publish.yml")); + } } \ No newline at end of file