From 6b0746d2bd7acc66a4207e892a2123f6090ea921 Mon Sep 17 00:00:00 2001 From: ema Date: Wed, 18 Dec 2024 20:27:22 +0800 Subject: [PATCH] First update UI layout --- BetterGenshinImpact.sln | 11 + BetterGenshinImpact/App.xaml.cs | 6 +- .../BetterGenshinImpact.csproj | 3 +- BetterGenshinImpact/Model/UpdateOption.cs | 12 + .../Service/Interface/IUpdateService.cs | 13 + BetterGenshinImpact/Service/UpdateService.cs | 307 ++++++++++++++++++ .../Threading/SemaphoreSlimParallel.cs | 59 ++++ .../View/Controls/Webview/WebpagePanel.cs | 3 +- .../View/Controls/Webview/WebpageWindow.cs | 6 +- .../View/Windows/CheckUpdateWindow.xaml | 74 +++++ .../View/Windows/CheckUpdateWindow.xaml.cs | 95 ++++++ .../ViewModel/MainWindowViewModel.cs | 61 +--- Build/Updater/Program.cs | 44 +++ Build/Updater/Updater.csproj | 9 + 14 files changed, 632 insertions(+), 71 deletions(-) create mode 100644 BetterGenshinImpact/Model/UpdateOption.cs create mode 100644 BetterGenshinImpact/Service/Interface/IUpdateService.cs create mode 100644 BetterGenshinImpact/Service/UpdateService.cs create mode 100644 BetterGenshinImpact/Threading/SemaphoreSlimParallel.cs create mode 100644 BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml create mode 100644 BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml.cs create mode 100644 Build/Updater/Program.cs create mode 100644 Build/Updater/Updater.csproj diff --git a/BetterGenshinImpact.sln b/BetterGenshinImpact.sln index 3fdb2494..30c7a926 100644 --- a/BetterGenshinImpact.sln +++ b/BetterGenshinImpact.sln @@ -27,6 +27,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterGenshinImpact.Test", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fischless.WindowsInput", "Fischless.WindowsInput\Fischless.WindowsInput.csproj", "{9D00BC7A-9280-4AC9-8951-4502EDB71B76}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Updater", "Build\Updater\Updater.csproj", "{F18CF5A3-A83C-4CC6-8150-D3C40EC3140F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -123,6 +125,14 @@ Global {9D00BC7A-9280-4AC9-8951-4502EDB71B76}.Release|Any CPU.Build.0 = Release|x64 {9D00BC7A-9280-4AC9-8951-4502EDB71B76}.Release|x64.ActiveCfg = Release|x64 {9D00BC7A-9280-4AC9-8951-4502EDB71B76}.Release|x64.Build.0 = Release|x64 + {F18CF5A3-A83C-4CC6-8150-D3C40EC3140F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F18CF5A3-A83C-4CC6-8150-D3C40EC3140F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F18CF5A3-A83C-4CC6-8150-D3C40EC3140F}.Debug|x64.ActiveCfg = Debug|Any CPU + {F18CF5A3-A83C-4CC6-8150-D3C40EC3140F}.Debug|x64.Build.0 = Debug|Any CPU + {F18CF5A3-A83C-4CC6-8150-D3C40EC3140F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F18CF5A3-A83C-4CC6-8150-D3C40EC3140F}.Release|Any CPU.Build.0 = Release|Any CPU + {F18CF5A3-A83C-4CC6-8150-D3C40EC3140F}.Release|x64.ActiveCfg = Release|Any CPU + {F18CF5A3-A83C-4CC6-8150-D3C40EC3140F}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -130,6 +140,7 @@ Global GlobalSection(NestedProjects) = preSolution {AB85DA23-EB8F-4FBF-A7FA-35CE05B23C15} = {458E1106-43A4-47E6-B11B-D243035D4C76} {673344BC-B860-44AE-AD88-D33465BDE25B} = {458E1106-43A4-47E6-B11B-D243035D4C76} + {F18CF5A3-A83C-4CC6-8150-D3C40EC3140F} = {458E1106-43A4-47E6-B11B-D243035D4C76} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {352D8B78-9DE3-4E58-985F-FADD22594DB4} diff --git a/BetterGenshinImpact/App.xaml.cs b/BetterGenshinImpact/App.xaml.cs index 9985f237..9e35c50f 100644 --- a/BetterGenshinImpact/App.xaml.cs +++ b/BetterGenshinImpact/App.xaml.cs @@ -10,8 +10,8 @@ using BetterGenshinImpact.View; using BetterGenshinImpact.View.Pages; using BetterGenshinImpact.ViewModel; using BetterGenshinImpact.ViewModel.Pages; +using BetterGenshinImpact.ViewModel.Pages.View; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Serilog; @@ -22,9 +22,6 @@ using System.Diagnostics; using System.IO; using System.Threading.Tasks; using System.Windows; -using BetterGenshinImpact.View.Pages.View; -using BetterGenshinImpact.ViewModel.Pages.OneDragon; -using BetterGenshinImpact.ViewModel.Pages.View; using Wpf.Ui; using Wpf.Ui.Violeta.Controls; @@ -77,6 +74,7 @@ public partial class App : Application services.AddHostedService(); // Page resolver service services.AddSingleton(); + services.AddSingleton(); // Service containing navigation, same as INavigationWindow... but without window services.AddSingleton(); diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj index 20ceaf41..8ca5a8ad 100644 --- a/BetterGenshinImpact/BetterGenshinImpact.csproj +++ b/BetterGenshinImpact/BetterGenshinImpact.csproj @@ -42,6 +42,7 @@ + @@ -71,7 +72,7 @@ - + diff --git a/BetterGenshinImpact/Model/UpdateOption.cs b/BetterGenshinImpact/Model/UpdateOption.cs new file mode 100644 index 00000000..eb68bf53 --- /dev/null +++ b/BetterGenshinImpact/Model/UpdateOption.cs @@ -0,0 +1,12 @@ +namespace BetterGenshinImpact.Model; + +public sealed class UpdateOption +{ + public UpdateTrigger Trigger { get; set; } = default; +} + +public enum UpdateTrigger +{ + Auto, + Manual, +} diff --git a/BetterGenshinImpact/Service/Interface/IUpdateService.cs b/BetterGenshinImpact/Service/Interface/IUpdateService.cs new file mode 100644 index 00000000..130047ea --- /dev/null +++ b/BetterGenshinImpact/Service/Interface/IUpdateService.cs @@ -0,0 +1,13 @@ +using BetterGenshinImpact.Model; +using System.Threading.Tasks; + +namespace BetterGenshinImpact.Service.Interface; + +public interface IUpdateService +{ + /// + /// I will check the update and completed the update if needed + /// + /// + public Task CheckUpdateAsync(UpdateOption option); +} diff --git a/BetterGenshinImpact/Service/UpdateService.cs b/BetterGenshinImpact/Service/UpdateService.cs new file mode 100644 index 00000000..a9b4a73a --- /dev/null +++ b/BetterGenshinImpact/Service/UpdateService.cs @@ -0,0 +1,307 @@ +using BetterGenshinImpact.Core.Config; +using BetterGenshinImpact.Helpers; +using BetterGenshinImpact.Helpers.Http; +using BetterGenshinImpact.Model; +using BetterGenshinImpact.Service.Interface; +using BetterGenshinImpact.Threading; +using BetterGenshinImpact.View.Windows; +using Downloader; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Http.Json; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; + +namespace BetterGenshinImpact.Service; + +public class UpdateService : IUpdateService +{ + private readonly ILogger _logger; + private readonly IConfigService _configService; + + private const string InstallationUrlPrefix = "https://raw.githubusercontent.com/bettergi/bettergi-installation-data/refs/heads/main/installation"; + private const string HashUrl = "https://raw.githubusercontent.com/bettergi/bettergi-installation-data/refs/heads/main/hash.json"; + private const string NoticUrl = "https://hui-config.oss-cn-hangzhou.aliyuncs.com/bgi/notice.json"; + private const string DownloadPageUrl = "https://bgi.huiyadan.com/download.html"; + + public AllConfig Config { get; set; } + + public UpdateService(IConfigService configService) + { + _logger = App.GetLogger(); + _configService = configService; + Config = _configService.Get(); + } + + private class XYZ + { + public string X { get; set; } = string.Empty; + public string Y { get; set; } = string.Empty; + public string Z { get; set; } = string.Empty; + } + + /// + /// Please call me in main thread + /// + /// + public async Task CheckUpdateAsync(UpdateOption option) + { + try + { + string newVersion = await GetLatestVersionAsync(); + +#if DEBUG && true + newVersion = "256.256.256.256"; +#endif + + if (string.IsNullOrWhiteSpace(newVersion)) + { + return; + } + + if (!Global.IsNewVersion(newVersion)) + { + return; + } + + if (!string.IsNullOrEmpty(Config.NotShowNewVersionNoticeEndVersion) + && !Global.IsNewVersion(Config.NotShowNewVersionNoticeEndVersion, newVersion)) + { + return; + } + + CheckUpdateWindow win = new() + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner, + Title = $"发现新版本 {newVersion}", + UserInteraction = async (sender, button) => + { + CheckUpdateWindow win = (CheckUpdateWindow)sender; + CancellationTokenSource? tokenSource = new(); + + switch (button) + { + case CheckUpdateWindow.CheckUpdateWindowButton.BackgroundUpdate: + // TBD + break; + + case CheckUpdateWindow.CheckUpdateWindowButton.OtherUpdate: + Process.Start(new ProcessStartInfo(DownloadPageUrl) { UseShellExecute = true }); + break; + + case CheckUpdateWindow.CheckUpdateWindowButton.Update: + { + win.ShowUpdateStatus = true; + + try + { + win.UpdateStatusMessage = "正在获取更新代理..."; + + (string fastProxyUrl, string jsonString) = await ProxySpeedTester.GetFastestProxyAsync(HashUrl); + + win.UpdateStatusMessage = $"获取更新代理成功 {fastProxyUrl.Replace("{0}", string.Empty)}"; + + Dictionary? hashDict = JsonConvert.DeserializeObject>(jsonString); + + if (hashDict == null) + { + win.UpdateStatusMessage = "获取更新列表失败,更新已取消。"; + return; + } + + List<(string, string, string)> downloadList = []; + + foreach (KeyValuePair hashPair in hashDict) + { + string targetFileName = Path.GetFullPath($@".\update\{hashPair.Key}.zip"); + string sourceFileName = Path.GetFullPath($@".\{hashPair.Value}"); + + if (IsNeedDownload(sourceFileName, hashPair.Value)) + { + string url = string.Format(fastProxyUrl, $"{InstallationUrlPrefix}/{hashPair.Key}.zip").Replace("\\", "/"); + downloadList.Add((hashPair.Key, url, targetFileName)); + } + } + + SemaphoreSlimParallel downloadParallel = await SemaphoreSlimParallel.ForEach(downloadList, async item => + { + DownloadConfiguration downloadOpt = new(); + DownloadService downloader = new(downloadOpt); + + //downloader.DownloadFileCompleted += (sender, e) => + //{ + // if (e.Error != null) + // { + // _logger.LogError(e.Error, "下载失败"); + // win.UpdateStatusMessage = $"下载失败:{e.Error.Message}"; + // } + //}; + + (string shortName, string url, string fileName) = item; + + win.UpdateStatusMessage = $"正在下载 {shortName}"; + await downloader.DownloadFileTaskAsync(url, fileName, cancellationToken: tokenSource.Token); + + win.UpdateStatusMessage = $"正在解压 {shortName}"; + }, 3); + + await downloadParallel.DisposeAsync(); + + win.UpdateStatusMessage = "下载已完成"; + } + catch (Exception e) + { + _logger.LogError(e, "更新失败"); + win.UpdateStatusMessage = $"更新失败:{e.Message}"; + } + } + break; + + case CheckUpdateWindow.CheckUpdateWindowButton.Ignore: + Config.NotShowNewVersionNoticeEndVersion = newVersion; + win.Close(); + break; + + case CheckUpdateWindow.CheckUpdateWindowButton.Cancel: + if (tokenSource != null) + { + if (MessageBox.Question("正在更新中,确定要取消更新吗?") == MessageBoxResult.Yes) + { + win.ShowUpdateStatus = false; + tokenSource?.Cancel(); + win.Close(); + } + } + else + { + win.ShowUpdateStatus = false; + win.Close(); + } + break; + } + } + }; + + win.NavigateToHtml(await GetReleaseMarkdownHtmlAsync()); + win.ShowDialog(); + } + catch (Exception e) + { + Debug.WriteLine("获取最新版本信息失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); + _logger.LogWarning("获取 BetterGI 最新版本信息失败"); + } + } + + private async Task GetLatestVersionAsync() + { + try + { + using HttpClient httpClient = new(); + Notice? notice = await httpClient.GetFromJsonAsync(NoticUrl); + + if (notice != null) + { + return notice.Version; + } + } + catch (Exception e) + { + _ = e; + } + + return string.Empty; + } + + private async Task GetReleaseMarkdownHtmlAsync() + { + try + { + 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"); + var jsonDict = JsonConvert.DeserializeObject>(jsonString); + + if (jsonDict != null) + { + string? name = jsonDict["name"] as string; + string? body = jsonDict["body"] as string; + string md = $"# {name}{new string('\n', 2)}{body}"; + + md = WebUtility.HtmlEncode(md); + string md2html = ResourceHelper.GetString($"pack://application:,,,/Assets/Strings/md2html.html", Encoding.UTF8); + var html = md2html.Replace("{{content}}", md); + + return html; + } + } + catch (Exception e) + { + _ = e; + } + + return GetReleaseMarkdownHtmlFallback(); + } + + private string GetReleaseMarkdownHtmlFallback() + { + return + """ + + + + + + 更新日志 + + + +
+ 获取更新日志失败,请自行选择是否更新! +
+ + + """; + } + + private static bool IsNeedDownload(string sourceFileName, string targetSha256) + { + if (File.Exists(sourceFileName)) + { + using SHA256 sha256 = SHA256.Create(); + using FileStream fileStream = new(sourceFileName, FileMode.Open, FileAccess.Read); + byte[] hashBytes = sha256.ComputeHash(fileStream); + string sourceSha256 = BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToUpper(); + + if (sourceSha256 == targetSha256) + { + return false; + } + } + return true; + } +} diff --git a/BetterGenshinImpact/Threading/SemaphoreSlimParallel.cs b/BetterGenshinImpact/Threading/SemaphoreSlimParallel.cs new file mode 100644 index 00000000..560c5483 --- /dev/null +++ b/BetterGenshinImpact/Threading/SemaphoreSlimParallel.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace BetterGenshinImpact.Threading; + +public class SemaphoreSlimParallel : IAsyncDisposable +{ + private readonly SemaphoreSlim _semaphore; + private readonly List _tasks = []; + + private SemaphoreSlimParallel(int maxDegreeOfParallelism) + { + _semaphore = new SemaphoreSlim(maxDegreeOfParallelism); + } + + public static async Task ForEach( + IEnumerable items, + Func action, + int maxDegreeOfParallelism, + CancellationToken cancellationToken = default) + { + var parallelExecutor = new SemaphoreSlimParallel(maxDegreeOfParallelism); + + foreach (var item in items) + { + await parallelExecutor._semaphore.WaitAsync(cancellationToken); + var task = Task.Run(async () => + { + try + { + await action(item); + } + finally + { + parallelExecutor._semaphore.Release(); + } + }, cancellationToken); + + parallelExecutor._tasks.Add(task); + } + + return parallelExecutor; + } + + public async ValueTask DisposeAsync() + { + try + { + // 等待所有任务完成 + await Task.WhenAll(_tasks); + } + finally + { + _semaphore.Dispose(); + } + } +} diff --git a/BetterGenshinImpact/View/Controls/Webview/WebpagePanel.cs b/BetterGenshinImpact/View/Controls/Webview/WebpagePanel.cs index ef645539..f6d03241 100644 --- a/BetterGenshinImpact/View/Controls/Webview/WebpagePanel.cs +++ b/BetterGenshinImpact/View/Controls/Webview/WebpagePanel.cs @@ -1,5 +1,4 @@ -using BetterGenshinImpact.ViewModel.Pages; -using Microsoft.Web.WebView2.Core; +using Microsoft.Web.WebView2.Core; using Microsoft.Web.WebView2.Wpf; using System; using System.Diagnostics; diff --git a/BetterGenshinImpact/View/Controls/Webview/WebpageWindow.cs b/BetterGenshinImpact/View/Controls/Webview/WebpageWindow.cs index 950bfa1d..168edea7 100644 --- a/BetterGenshinImpact/View/Controls/Webview/WebpageWindow.cs +++ b/BetterGenshinImpact/View/Controls/Webview/WebpageWindow.cs @@ -1,7 +1,6 @@ -using System; +using Microsoft.Web.WebView2.Wpf; +using System; using System.Windows; -using System.Windows.Media; -using Microsoft.Web.WebView2.Wpf; using Wpf.Ui.Controls; namespace BetterGenshinImpact.View.Controls.Webview; @@ -20,7 +19,6 @@ public class WebpageWindow : Window }; Content = wp; - // Background = new SolidColorBrush(Color.FromRgb(0x20, 0x20, 0x20)); } protected override void OnSourceInitialized(EventArgs e) diff --git a/BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml b/BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml new file mode 100644 index 00000000..0b72babc --- /dev/null +++ b/BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml.cs b/BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml.cs new file mode 100644 index 00000000..7b9b7d97 --- /dev/null +++ b/BetterGenshinImpact/View/Windows/CheckUpdateWindow.xaml.cs @@ -0,0 +1,95 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using System; +using System.ComponentModel; +using System.Threading.Tasks; +using Wpf.Ui.Controls; + +namespace BetterGenshinImpact.View.Windows; + +[ObservableObject] +public partial class CheckUpdateWindow : FluentWindow +{ + public Func UserInteraction = null!; + + [ObservableProperty] + private bool showUpdateStatus = false; + + [ObservableProperty] + private string updateStatusMessage = string.Empty; + + public CheckUpdateWindow() + { + DataContext = this; + InitializeComponent(); + + Closing += OnClosing; + } + + protected void OnClosing(object? sender, CancelEventArgs e) + { + if (ShowUpdateStatus) + { + e.Cancel = true; + } + } + + public void NavigateToHtml(string html) + { + WebpagePanel?.NavigateToHtml(html); + } + + [RelayCommand] + private async Task BackgroundUpdateAsync() + { + if (UserInteraction != null) + { + await UserInteraction.Invoke(this, CheckUpdateWindowButton.BackgroundUpdate); + } + } + + [RelayCommand] + private async Task OtherUpdateAsync() + { + if (UserInteraction != null) + { + await UserInteraction.Invoke(this, CheckUpdateWindowButton.OtherUpdate); + } + } + + [RelayCommand] + private async Task UpdateAsync() + { + if (UserInteraction != null) + { + await UserInteraction.Invoke(this, CheckUpdateWindowButton.Update); + } + } + + [RelayCommand] + private async Task IgnoreAsync() + { + if (UserInteraction != null) + { + await UserInteraction.Invoke(this, CheckUpdateWindowButton.Ignore); + } + } + + [RelayCommand] + private async Task CancelAsync() + { + if (UserInteraction != null) + { + await UserInteraction.Invoke(this, CheckUpdateWindowButton.Cancel); + } + } + + public enum CheckUpdateWindowButton + { + BackgroundUpdate, + OtherUpdate, + Update, + Ignore, + Cancel, + } +} diff --git a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs index b0e97b37..245dcc91 100644 --- a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs +++ b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs @@ -14,8 +14,6 @@ using System; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Net.Http; -using System.Net.Http.Json; using System.Threading.Tasks; using System.Windows; using Wpf.Ui; @@ -100,15 +98,7 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel MessageBox.Warning("PaddleOcr预热失败,解决方案:https://bgi.huiyadan.com/faq.html," + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); } - try - { - await Task.Run(GetNewestInfoAsync); - } - catch (Exception e) - { - Debug.WriteLine("获取最新版本信息失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); - _logger.LogWarning("获取 BetterGI 最新版本信息失败"); - } + await App.GetService()!.CheckUpdateAsync(new UpdateOption()); // Win11下 BitBlt截图方式不可用,需要关闭窗口优化功能 if (OsVersionHelper.IsWindows11_OrGreater && TaskContext.Instance().Config.AutoFixWin11BitBlt) @@ -119,53 +109,4 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel // 更新仓库 ScriptRepoUpdater.Instance.AutoUpdate(); } - - private async Task GetNewestInfoAsync() - { - try - { - using var httpClient = new HttpClient(); - var notice = await httpClient.GetFromJsonAsync(@"https://hui-config.oss-cn-hangzhou.aliyuncs.com/bgi/notice.json"); - if (notice != null && !string.IsNullOrWhiteSpace(notice.Version)) - { - if (Global.IsNewVersion(notice.Version)) - { - if (!string.IsNullOrEmpty(Config.NotShowNewVersionNoticeEndVersion) - && !Global.IsNewVersion(Config.NotShowNewVersionNoticeEndVersion, notice.Version)) - { - return; - } - - await UIDispatcherHelper.Invoke(async () => - { - var uiMessageBox = new Wpf.Ui.Controls.MessageBox - { - Title = "更新提示", - Content = $"存在最新版本 {notice.Version},点击确定前往下载页面下载最新版本", - PrimaryButtonText = "确定", - SecondaryButtonText = "不再提示", - CloseButtonText = "取消", - WindowStartupLocation = WindowStartupLocation.CenterOwner, - Owner = Application.Current.MainWindow, - }; - - var result = await uiMessageBox.ShowDialogAsync(); - if (result == Wpf.Ui.Controls.MessageBoxResult.Primary) - { - Process.Start(new ProcessStartInfo("https://bgi.huiyadan.com/download.html") { UseShellExecute = true }); - } - else if (result == Wpf.Ui.Controls.MessageBoxResult.Secondary) - { - Config.NotShowNewVersionNoticeEndVersion = notice.Version; - } - }); - } - } - } - catch (Exception e) - { - Debug.WriteLine("获取最新版本信息失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); - _logger.LogWarning("获取 BetterGI 最新版本信息失败"); - } - } } diff --git a/Build/Updater/Program.cs b/Build/Updater/Program.cs new file mode 100644 index 00000000..4a662aa3 --- /dev/null +++ b/Build/Updater/Program.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; +using System.Threading; + +namespace Updater; + +internal sealed class Program +{ + private static void Main(string[] args) + { + if (args.Length < 2) + { + // Avoid user interaction + Environment.ExitCode = 1; + return; + } + + // Chattering ms + Thread.Sleep(200); + + string sourcePath = args[0]; + string targetPath = args[1]; + + if (!Directory.Exists(sourcePath)) + { + Environment.ExitCode = 1; + return; + } + + if (!Directory.Exists(targetPath)) + { + Directory.CreateDirectory(targetPath); + } + + // No fallback measures + foreach (string file in Directory.GetFiles(sourcePath)) + { + string fileName = Path.GetFileName(file); + string targetFile = Path.Combine(targetPath, fileName); + + File.Copy(file, targetFile, true); + } + } +} diff --git a/Build/Updater/Updater.csproj b/Build/Updater/Updater.csproj new file mode 100644 index 00000000..ec7f2658 --- /dev/null +++ b/Build/Updater/Updater.csproj @@ -0,0 +1,9 @@ + + + + Exe + net472 + latest + + +