AppUpdate

This commit is contained in:
Aigio Liu
2021-04-25 16:28:06 +08:00
parent 101114f841
commit ca294cb77a
19 changed files with 366 additions and 87 deletions
@@ -22,8 +22,9 @@ namespace System.Application.Converters
}
[Obsolete("use HttpClient")]
protected static Bitmap DownloadImage(string url, int width = 0)
protected static Bitmap? DownloadImage(string? url, int width = 0)
{
if (url == null) return null;
using var web = new WebClient();
var ua = DI.Get<IHttpPlatformHelper>().UserAgent;
web.Headers.Add("User-Agent", ua);
@@ -1,5 +1,7 @@
using Microsoft.Extensions.Options;
using Avalonia.Controls.ApplicationLifetimes;
using Microsoft.Extensions.Options;
using System.Application.Models;
using AvaloniaApplication = Avalonia.Application;
namespace System.Application.Services.Implementation
{
@@ -15,12 +17,15 @@ namespace System.Application.Services.Implementation
this.app = app;
}
protected override void OnExistNewVersion()
protected override async void OnExistNewVersion()
{
//if (WindowService.Current.MainWindow.Dialog($"检测到新版本更新内容:{UpdateInfo.body}{Environment.NewLine}是否立即下载更新?", $"{ProductInfo.Title} | 更新提示") == true)
//{
// DownloadUpdate();
//}
if (AvaloniaApplication.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
if (desktop.Windows.Any_Nullable(x => x.IsActive))
{
await IShowWindowService.Instance.Show(typeof(object), CustomWindow.NewVersion);
}
}
}
protected override void OnExit()
@@ -36,8 +36,11 @@ namespace System.Application.Services.Implementation
{
var windowType = GetWindowType(customWindow);
var window = (Window)Activator.CreateInstance(windowType);
if (viewModel == null) viewModel = (WindowViewModel)Activator.CreateInstance(typeWindowViewModel);
if (!string.IsNullOrEmpty(title))
if (viewModel == null && typeWindowViewModel != typeof(object))
{
viewModel = (WindowViewModel)Activator.CreateInstance(typeWindowViewModel);
}
if (!string.IsNullOrEmpty(title) && viewModel != null)
{
viewModel.Title = title;
}
@@ -87,7 +90,7 @@ namespace System.Application.Services.Implementation
BindingDialogWindowViewModel(window, dialogWindowViewModel, actionDialogWindowViewModel);
}
}
window.DataContext = viewModel;
if (viewModel != null) window.DataContext = viewModel;
if (isDialog)
{
await IDesktopAvaloniaAppService.Instance.ShowDialogWindow(window);
@@ -13,7 +13,7 @@
</ExperimentalAcrylicBorder.Material>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="10 6 10 6">
<Image Source="/Application/UI/Assets/Icon.ico" Height="18" Width="18" Margin="0,0,10,0"/>
<TextBlock IsHitTestVisible="False" Grid.Column="1" Text="{Binding Title}" VerticalAlignment="Center" Foreground="{DynamicResource HighlightForegroundBrushKey}" FontSize="14"/>
<TextBlock IsHitTestVisible="False" Grid.Column="1" Text="{ReflectionBinding $parent[Window].Title}" VerticalAlignment="Center" Foreground="{DynamicResource HighlightForegroundBrushKey}" FontSize="14"/>
</StackPanel>
</ExperimentalAcrylicBorder>
<ExperimentalAcrylicBorder DockPanel.Dock="Bottom" IsHitTestVisible="False">
@@ -0,0 +1,78 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="620" d:DesignHeight="100"
Width="620" Height="100"
MinWidth="620" MinHeight="100"
x:Class="System.Application.UI.Views.Windows.NewVersionWindow"
xmlns:resx="clr-namespace:System.Application.UI.Resx;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:ccl_services="clr-namespace:System.Application.Services;assembly=System.Application.SteamTools.Client"
xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls"
xmlns:ms="clr-namespace:System.Application.Models.Settings;assembly=System.Application.SteamTools.Client.Desktop"
FontFamily="{Binding Source={x:Static ms:UISettings.FontName},Path=Value, Mode=OneWay,Converter={StaticResource NameToFontFamilyConverter}}"
UseLayoutRounding="True"
WindowStartupLocation="CenterOwner"
SizeToContent="WidthAndHeight"
ShowInTaskbar="False"
Padding="0" Background="Transparent"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
ExtendClientAreaTitleBarHeightHint="30"
CanResize="False"
Title="{ReflectionBinding Path=Res.NewVersionUpdateTitle,Mode=OneWay,Source={x:Static resx:R.Current}}">
<Grid RowDefinitions="1,30,*,Auto,Auto,1">
<controls:TitleBar Grid.RowSpan="5"/>
<StackPanel Margin="12 10 12 0" Grid.Row="2" x:Name="content">
<DockPanel>
<TextBlock Text="{ReflectionBinding Path=Res.UpdateContent,Mode=OneWay,Source={x:Static resx:R.Current}}" DockPanel.Dock="Top" Margin="0,0,0,8" FontSize="19"/>
<TextBlock Text="{ReflectionBinding Path=NewVersionInfoDesc,Mode=OneWay,Source={x:Static ccl_services:IAppUpdateService.Instance}}"
MaxWidth="596"
Margin="12,0"
FontSize="15"
HorizontalAlignment="Left"
TextWrapping="WrapWithOverflow"
VerticalAlignment="Center"/>
</DockPanel>
<Border Margin="0 11 0 11">
<Separator Classes="Separator"/>
</Border>
</StackPanel>
<StackPanel Grid.Row="3"
IsVisible="True"
Orientation="Vertical"
Margin="10,0">
<Panel Margin="0,0,0,10">
<ProgressBar
Height="28"
Value="{ReflectionBinding Path=TotalProgressValue,Mode=OneWay,Source={x:Static ccl_services:IAppUpdateService.Instance}}"/>
<TextBlock
Text="{ReflectionBinding Path=ProgressString,Mode=OneWay,Source={x:Static ccl_services:IAppUpdateService.Instance}}"
Foreground="White"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Panel>
</StackPanel>
<WrapPanel Grid.Row="4"
IsVisible="True"
HorizontalAlignment="Right"
Margin="10,0">
<Button
MinWidth="90"
Padding="30,6"
Margin="10,0,0,10"
IsDefault="True"
Content="{ReflectionBinding Path=Res.StartUpdate,Mode=OneWay,Source={x:Static resx:R.Current}}"
Command="{ReflectionBinding Path=StartUpdateCommand,Mode=OneWay,Source={x:Static ccl_services:IAppUpdateService.Instance}}"/>
<Button
x:Name="BtnCancel"
MinWidth="90"
Padding="30,6"
Margin="10,0,0,10"
IsCancel="True"
Content="{ReflectionBinding Path=Res.DoNotUpdate,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
</WrapPanel>
</Grid>
</Window>
@@ -0,0 +1,26 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace System.Application.UI.Views.Windows
{
public class NewVersionWindow : FluentWindow
{
public Button BtnCancel { get; }
public NewVersionWindow()
{
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
BtnCancel = this.FindControl<Button>(nameof(BtnCancel));
BtnCancel.Click += (_, _) => Close();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}
+1
View File
@@ -12,5 +12,6 @@
AuthTrade,
ChangeBindPhoneNumber,
UserProfile,
NewVersion,
}
}
@@ -17,8 +17,6 @@ namespace System.Application.Services.Implementation
protected override Version OSVersion => Environment.OSVersion.Version;
protected sealed override void OpenInAppStore() => throw new NotImplementedException();
/// <summary>
/// 当更新下载完毕并校验完成时,即将退出程序之前
/// </summary>
@@ -39,20 +37,16 @@ namespace System.Application.Services.Implementation
Directory.Delete(dirPath, true);
}
CurrentProgressValue = 0;
void OnReport(float value) => CurrentProgressValue = value;
if (TarGZipHelper.Unpack(value, dirPath, progress: new Progress<float>(OnReport)))
if (TarGZipHelper.Unpack(value, dirPath, progress: new Progress<float>(OnReportDecompressing), maxProgress: MaxProgressValue))
{
ClearProgressValue(MaxProgressValue);
OnReport(MaxProgressValue);
IOPath.FileTryDelete(value);
OverwriteUpgradePrivate(dirPath);
}
else
{
toast.Show(SR.UpdateUnpackFail);
ClearProgressValue(MaxProgressValue);
OnReport(MaxProgressValue);
}
}
@@ -60,7 +54,7 @@ namespace System.Application.Services.Implementation
{
OnExit();
var updateCommandPath = Path.Combine(AppContext.BaseDirectory, "update.cmd");
var updateCommandPath = Path.Combine(IOPath.CacheDirectory, "update.cmd");
IOPath.FileIfExistsItDelete(updateCommandPath);
var echo = SR.ProgramUpdateEcho;
+5 -3
View File
@@ -60,10 +60,12 @@ namespace System.Application
/// <param name="dirPath">要解压的文件夹路径,文件夹必须不存在</param>
/// <param name="progressMessage">进度消息监听</param>
/// <param name="progress">进度值监听</param>
/// <param name="maxProgress"></param>
/// <returns></returns>
public static bool Unpack(string filePath, string dirPath,
ProgressMessageHandler? progressMessage = null,
IProgress<float>? progress = null)
IProgress<float>? progress = null,
float maxProgress = 100f)
{
if (!File.Exists(filePath)) return false;
if (Directory.Exists(dirPath)) return false;
@@ -77,7 +79,7 @@ namespace System.Application
{
while (!isFinish)
{
var value = fs.Position / length;
var value = fs.Position / length * maxProgress;
progress.Report(value);
await Task.Delay(200);
}
@@ -89,7 +91,7 @@ namespace System.Application
if (progress != null) Task.Factory.StartNew(ProgressMonitor);
archive.ExtractContents(dirPath);
isFinish = true;
progress?.Report(1f);
progress?.Report(maxProgress);
return true;
}
}
+36
View File
@@ -510,6 +510,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 暂不更新 的本地化字符串。
/// </summary>
public static string DoNotUpdate {
get {
return ResourceManager.GetString("DoNotUpdate", resourceCulture);
}
}
/// <summary>
/// 查找类似 编辑 的本地化字符串。
/// </summary>
@@ -1303,6 +1312,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 Steam++ 版本更新 的本地化字符串。
/// </summary>
public static string NewVersionUpdateTitle {
get {
return ResourceManager.GetString("NewVersionUpdateTitle", resourceCulture);
}
}
/// <summary>
/// 查找类似 昵称 的本地化字符串。
/// </summary>
@@ -1600,6 +1618,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 开始更新 的本地化字符串。
/// </summary>
public static string StartUpdate {
get {
return ResourceManager.GetString("StartUpdate", resourceCulture);
}
}
/// <summary>
/// 查找类似 输入图中验证码 的本地化字符串。
/// </summary>
@@ -1853,6 +1880,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 更新内容 的本地化字符串。
/// </summary>
public static string UpdateContent {
get {
return ResourceManager.GetString("UpdateContent", resourceCulture);
}
}
/// <summary>
/// 查找类似 上传您的头像 的本地化字符串。
/// </summary>
@@ -268,6 +268,9 @@
<data name="DelAccount" xml:space="preserve">
<value>账号注销</value>
</data>
<data name="DoNotUpdate" xml:space="preserve">
<value>暂不更新</value>
</data>
<data name="Edit" xml:space="preserve">
<value>编辑</value>
</data>
@@ -535,6 +538,9 @@
<data name="More" xml:space="preserve">
<value>更多操作</value>
</data>
<data name="NewVersionUpdateTitle" xml:space="preserve">
<value>Steam++ 版本更新</value>
</data>
<data name="NickName" xml:space="preserve">
<value>昵称</value>
</data>
@@ -635,6 +641,9 @@
<data name="SMSCode" xml:space="preserve">
<value>短信验证代码</value>
</data>
<data name="StartUpdate" xml:space="preserve">
<value>开始更新</value>
</data>
<data name="SteamAccount" xml:space="preserve">
<value>Steam 账号</value>
</data>
@@ -720,6 +729,9 @@
<data name="UnsavedEditingWillBeDiscarded" xml:space="preserve">
<value>将丢弃未保存的编辑</value>
</data>
<data name="UpdateContent" xml:space="preserve">
<value>更新内容</value>
</data>
<data name="UploadYourAvatar" xml:space="preserve">
<value>上传您的头像</value>
</data>
@@ -85,8 +85,8 @@ namespace System.Application.UI.ViewModels
SettingsPageViewModel.Instance,
AboutPageViewModel.Instance,
#if DEBUG
//new DebugPageViewModel().AddTo(this),
// new DebugWebViewPageViewModel().AddTo(this),
new DebugPageViewModel().AddTo(this),
new DebugWebViewPageViewModel().AddTo(this),
#endif
#endregion
};
@@ -212,22 +212,24 @@ namespace System.Application.UI.ViewModels
public async void ShowDialogButton_Click()
{
Services.ToastService.Current.Notify("Test CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest Command");
DebugString += Services.ToastService.Current.Message + Environment.NewLine;
DebugString += Services.ToastService.Current.IsVisible + Environment.NewLine;
ToastService.Current.Notify("Test CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest CommandTest Command");
DebugString += ToastService.Current.Message + Environment.NewLine;
DebugString += ToastService.Current.IsVisible + Environment.NewLine;
var r = await MessageBoxCompat.ShowAsync(@"Steam++ v1.1.2 2021-01-29
更新内容
1、新增账号切换的状态栏右下角登录新账号功能
2、新增实时刷新获取Steam新登录的账号数据功能
3、新增FAQ常见问题疑难解答文本,可以在关于中找到它
4、优化配置文件备份机制,如果配置文件出错会提示还原上次读取成功的配置
5、优化错误日志记录,现在它更详细了
6、修复谷歌验证码代理方式为全局跳转recatpcha
7、修复配置文件加载时提示根元素错误
8、修复某些情况下开机自启失效问题", "Steam++", MessageBoxButtonCompat.OKCancel);
await IShowWindowService.Instance.Show(typeof(object), CustomWindow.NewVersion);
DebugString += r + Environment.NewLine;
// var r = await MessageBoxCompat.ShowAsync(@"Steam++ v1.1.2 2021-01-29
//更新内容
//1、新增账号切换的状态栏右下角登录新账号功能
//2、新增实时刷新获取Steam新登录的账号数据功能
//3、新增FAQ常见问题疑难解答文本,可以在关于中找到它
//4、优化配置文件备份机制,如果配置文件出错会提示还原上次读取成功的配置
//5、优化错误日志记录,现在它更详细了
//6、修复谷歌验证码代理方式为全局跳转recatpcha
//7、修复配置文件加载时提示根元素错误
//8、修复某些情况下开机自启失效问题", "Steam++", MessageBoxButtonCompat.OKCancel);
// DebugString += r + Environment.NewLine;
//.ContinueWith(s => DebugString += s.Result + Environment.NewLine);
+1 -1
View File
@@ -14,6 +14,6 @@ namespace System.Application
/// </summary>
/// <param name="imageId"></param>
/// <returns></returns>
public static string GetImageApiUrlById(Guid imageId) => string.Format(GetImageApiUrl, imageId, ICloudServiceClient.Instance.ApiBaseUrl);
public static string? GetImageApiUrlById(Guid imageId) => imageId == default ? default : string.Format(GetImageApiUrl, imageId, ICloudServiceClient.Instance.ApiBaseUrl);
}
}
+36
View File
@@ -69,6 +69,24 @@ namespace System.Application.Properties {
}
}
/// <summary>
/// 查找类似 正在校验:{0}% 的本地化字符串。
/// </summary>
internal static string CalcHashing_ {
get {
return ResourceManager.GetString("CalcHashing_", resourceCulture);
}
}
/// <summary>
/// 查找类似 正在校验({1}/{2}):{0}% 的本地化字符串。
/// </summary>
internal static string CalcHashing3_ {
get {
return ResourceManager.GetString("CalcHashing3_", resourceCulture);
}
}
/// <summary>
/// 查找类似 创建证书失败 的本地化字符串。
/// </summary>
@@ -78,6 +96,15 @@ namespace System.Application.Properties {
}
}
/// <summary>
/// 查找类似 正在解压:{0}% 的本地化字符串。
/// </summary>
internal static string Decompressing_ {
get {
return ResourceManager.GetString("Decompressing_", resourceCulture);
}
}
/// <summary>
/// 查找类似 正在下载:{0}% 的本地化字符串。
/// </summary>
@@ -87,6 +114,15 @@ namespace System.Application.Properties {
}
}
/// <summary>
/// 查找类似 正在下载({1}/{2}):{0}% 的本地化字符串。
/// </summary>
internal static string Downloading3_ {
get {
return ResourceManager.GetString("Downloading3_", resourceCulture);
}
}
/// <summary>
/// 查找类似 下载更新包失败,请稍后重试 的本地化字符串。
/// </summary>
+12
View File
@@ -120,10 +120,22 @@
<data name="AppName" xml:space="preserve">
<value>Steam++</value>
</data>
<data name="CalcHashing3_" xml:space="preserve">
<value>正在校验({1}/{2}):{0}%</value>
</data>
<data name="CalcHashing_" xml:space="preserve">
<value>正在校验:{0}%</value>
</data>
<data name="CreateCertificateFaild" xml:space="preserve">
<value>创建证书失败</value>
<comment>Fail</comment>
</data>
<data name="Decompressing_" xml:space="preserve">
<value>正在解压:{0}%</value>
</data>
<data name="Downloading3_" xml:space="preserve">
<value>正在下载({1}/{2}):{0}%</value>
</data>
<data name="Downloading_" xml:space="preserve">
<value>正在下载:{0}%</value>
</data>
+20 -6
View File
@@ -1,4 +1,5 @@
using System.Application.Models;
using System.Windows.Input;
namespace System.Application.Services
{
@@ -12,14 +13,14 @@ namespace System.Application.Services
public const float MaxProgressValue = 100f;
/// <summary>
/// 当前进度值
/// 进度值
/// </summary>
float CurrentProgressValue { get; }
float ProgressValue { get; }
/// <summary>
/// 总进度值
/// 进度值描述
/// </summary>
float TotalProgressValue { get; }
string ProgressString { get; }
/// <summary>
/// 是否支持服务端分发,如果返回 <see langword="false"/> 将不能使用 DownloadAsync 与 OverwriteUpgradeAsync
@@ -37,11 +38,24 @@ namespace System.Application.Services
/// </summary>
AppVersionDTO? NewVersionInfo { get; }
string NewVersionInfoDesc
{
get
{
var value = NewVersionInfo?.Description;
if (string.IsNullOrWhiteSpace(value)) return string.Empty;
var lines = value.Split(';', StringSplitOptions.RemoveEmptyEntries);
return string.Join(Environment.NewLine, lines);
}
}
/// <summary>
/// 检查更新,返回新版本信息
/// </summary>
/// <returns></returns>
void CheckUpdate();
/// <param name="force">是否强制检查,如果为 <see langword="false"/> 当有新版本内存中缓存时将跳过 api 请求</param>
void CheckUpdate(bool force = false);
ICommand StartUpdateCommand { get; }
}
#if DEBUG
@@ -1,20 +1,25 @@
using Microsoft.Extensions.Options;
using ReactiveUI;
using System.Application.Models;
using System.Application.Properties;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Windows.Input;
using static System.Application.Services.CloudService.Constants;
using static System.Application.Services.IAppUpdateService;
namespace System.Application.Services.Implementation
{
public abstract class AppUpdateServiceImpl : IAppUpdateService
public abstract class AppUpdateServiceImpl : ReactiveObject, IAppUpdateService
{
protected readonly ICloudServiceClient client;
protected readonly AppSettings settings;
protected readonly IToast toast;
public ICommand StartUpdateCommand { get; }
public AppUpdateServiceImpl(
IToast toast,
ICloudServiceClient client,
@@ -24,6 +29,7 @@ namespace System.Application.Services.Implementation
this.client = client;
settings = options.Value;
SupportedAbis = GetSupportedAbis();
StartUpdateCommand = ReactiveCommand.Create(StartUpdate);
}
protected virtual ArchitectureFlags GetSupportedAbis()
@@ -36,7 +42,7 @@ namespace System.Application.Services.Implementation
protected abstract Version OSVersion { get; }
public bool IsSupportedServerDistribution
public virtual bool IsSupportedServerDistribution
{
get
{
@@ -59,8 +65,20 @@ namespace System.Application.Services.Implementation
static bool isCheckUpdateing;
public async void CheckUpdate()
public async void CheckUpdate(bool force)
{
if (!force && IsExistUpdate)
{
if (NewVersionInfo.HasValue())
{
OnExistNewVersion();
}
else
{
IsExistUpdate = false;
}
}
if (isCheckUpdateing) return;
isCheckUpdateing = true;
@@ -113,7 +131,7 @@ namespace System.Application.Services.Implementation
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
static string GetPackName(AppVersionDTO m, bool isDirOrFile) => $"{m.Version}@{Hashs.String.Crc32(m.Id.ToStringN())}{(isDirOrFile ? "" : $".{FileEx.TAR_GZ}")}";
static string GetPackName(AppVersionDTO m, bool isDirOrFile) => $"{m.Version}@{Hashs.String.Crc32(m.Id.ToByteArray())}{(isDirOrFile ? "" : $".{FileEx.TAR_GZ}")}";
/// <summary>
/// 获取存放升级包缓存文件夹的目录
@@ -145,21 +163,43 @@ namespace System.Application.Services.Implementation
/// </summary>
const bool isSupportedResume = false;
public float CurrentProgressValue { get; protected set; }
public float TotalProgressValue { get; protected set; }
protected void ClearProgressValue(float value = 0f)
float _ProgressValue;
public float ProgressValue
{
CurrentProgressValue = value;
TotalProgressValue = value;
get => _ProgressValue;
protected set => this.RaiseAndSetIfChanged(ref _ProgressValue, value);
}
bool UpdatePackVerification(string filePath, string sha256, bool notChangeProgress = false)
string _ProgressString = string.Empty;
public string ProgressString
{
get => _ProgressString;
protected set => this.RaiseAndSetIfChanged(ref _ProgressString, value);
}
protected void OnReportDownloading3(float value, int current, int count) => OnReport(value, string.Format(SR.Downloading3_, value, current, count));
protected void OnReportCalcHashing3(float value, int current, int count) => OnReport(value, string.Format(SR.CalcHashing3_, value, current, count));
protected void OnReportDownloading(float value) => OnReport(value, string.Format(SR.Downloading_, value));
protected void OnReportCalcHashing(float value) => OnReport(value, string.Format(SR.CalcHashing_, value));
protected void OnReportDecompressing(float value) => OnReport(value, string.Format(SR.Decompressing_, value));
protected void OnReport(float value = 0f) => OnReport(value, string.Empty);
protected void OnReport(float value, string str)
{
ProgressValue = value;
ProgressString = str;
}
bool UpdatePackVerification(string filePath, string sha256, int current = 0, int count = 0)
{
void OnReportCalcHashing_(float value) => OnReportCalcHashing(value);
void OnReportCalcHashing3_(float value) => OnReportCalcHashing3(value, current, count);
Action<float> onReportCalcHashing = current > 0 && count > 0 ? OnReportCalcHashing3_ : OnReportCalcHashing_;
onReportCalcHashing(0);
var sha256_ = Hashs.String.SHA256(File.OpenRead(filePath)); // 改为带进度的哈希计算
if (!notChangeProgress && TotalProgressValue < MaxProgressValue) TotalProgressValue += 10;
return string.Equals(sha256_, sha256, StringComparison.OrdinalIgnoreCase);
var value = string.Equals(sha256_, sha256, StringComparison.OrdinalIgnoreCase);
onReportCalcHashing(MaxProgressValue);
return value;
}
/// <summary>
@@ -173,13 +213,13 @@ namespace System.Application.Services.Implementation
isDownloading = true;
ClearProgressValue();
OnReport();
var newVersionInfo = NewVersionInfo;
if (newVersionInfo.HasValue())
{
if (newVersionInfo.IncrementalUpdate.Any_Nullable())
if (newVersionInfo.IncrementalUpdate.Any_Nullable()) // 增量更新
{
if (Path.DirectorySeparatorChar != '\\')
{
@@ -190,7 +230,6 @@ namespace System.Application.Services.Implementation
}
}
// 增量更新
var packDirName = GetPackName(newVersionInfo, isDirOrFile: false);
var packDirPath = Path.Combine(GetPackCacheDirPath(!isSupportedResume), packDirName);
@@ -218,23 +257,26 @@ namespace System.Application.Services.Implementation
}
}
int i = 1;
foreach (var item in incrementalUpdate)
{
void OnReportDownloading3_(float value) => OnReportDownloading3(value, i, incrementalUpdate.Count);
var fileName = item.Value;
var cacheFileName = fileName + FileExDownloadCache;
var requestUri = AppVersionDTO.GetRequestUri(item.Key.FileId);
OnReport(0);
OnReportDownloading3_(0f);
var rsp = await client.Download(
isAnonymous: true,
requestUri: requestUri,
cacheFileName,
new Progress<float>(OnReport));
new Progress<float>(OnReportDownloading3_));
if (rsp.IsSuccess)
{
File.Move(cacheFileName, fileName);
if (!UpdatePackVerification(fileName, item.Key.SHA256, notChangeProgress: true))
if (!UpdatePackVerification(fileName, item.Key.SHA256, i, incrementalUpdate.Count))
{
Fail(SR.UpdatePackVerificationFail);
break;
@@ -245,29 +287,33 @@ namespace System.Application.Services.Implementation
Fail(SR.DownloadUpdateFail);
break;
}
TotalProgressValue += incrementalUpdate.Count / 100f;
i++;
}
ClearProgressValue(MaxProgressValue);
OnReport(MaxProgressValue);
OverwriteUpgrade(packDirPath, isIncrement: true);
}
else
else // 全量更新
{
// 全量更新
var compressed = newVersionInfo.Downloads.FirstOrDefault(x => x.DownloadType == AppDownloadType.Compressed);
if (compressed.HasValue())
var downloadType = DI.Platform switch
{
Platform.Windows or Platform.Linux or Platform.Apple => AppDownloadType.Compressed,
Platform.Android => AppDownloadType.Install,
_ => throw new PlatformNotSupportedException(),
};
var download = newVersionInfo.Downloads.FirstOrDefault(x => x.DownloadType == downloadType);
if (download.HasValue()) // 压缩包格式是否正确
{
var packFileName = GetPackName(newVersionInfo, isDirOrFile: true);
var packFilePath = Path.Combine(GetPackCacheDirPath(!isSupportedResume), packFileName);
if (File.Exists(packFilePath)) // 存在安装包文件
if (File.Exists(packFilePath)) // 存在压缩包文件
{
if (UpdatePackVerification(packFilePath, compressed.SHA256)) // (已有文件)哈希验证成功,进行覆盖安装
if (UpdatePackVerification(packFilePath, download.SHA256)) // (已有文件)哈希验证成功,进行覆盖安装
{
OverwriteUpgrade(packFilePath, isIncrement: false);
goto end;
}
else // 验证文件失败,删除源文件,将会重新下载 --提示用户,然后结束本次逻辑
else // 验证文件失败,删除源文件,将会重新下载
{
File.Delete(packFilePath);
}
@@ -275,22 +321,22 @@ namespace System.Application.Services.Implementation
var cacheFileName = packFileName + FileExDownloadCache;
var requestUri = AppVersionDTO.GetRequestUri(compressed.FileId);
var requestUri = AppVersionDTO.GetRequestUri(download.FileId);
OnReportDownloading(0f);
var rsp = await client.Download(
isAnonymous: true,
requestUri: requestUri,
cacheFileName,
new Progress<float>(OnReport));
new Progress<float>(OnReportDownloading));
if (rsp.IsSuccess)
{
File.Move(cacheFileName, packFileName);
if (UpdatePackVerification(packFilePath, compressed.SHA256)) // (下载文件)哈希验证成功,进行覆盖安装
if (UpdatePackVerification(packFilePath, download.SHA256)) // (下载文件)哈希验证成功,进行覆盖安装
{
OverwriteUpgrade(packFileName, isIncrement: false);
OnReport(MaxProgressValue);
if (TotalProgressValue < 50) TotalProgressValue = 50;
OnReportDownloading(MaxProgressValue);
}
else
{
@@ -307,14 +353,13 @@ namespace System.Application.Services.Implementation
Fail("The new version compressed package is missing, please contact the administrator.");
}
}
void OnReport(float value) => CurrentProgressValue = value;
}
end: isDownloading = false;
void Fail(string error)
{
toast.Show(error);
ClearProgressValue(MaxProgressValue);
OnReport(MaxProgressValue);
}
}
@@ -331,6 +376,18 @@ namespace System.Application.Services.Implementation
/// <summary>
/// 在应用商店中打开
/// </summary>
protected abstract void OpenInAppStore();
protected virtual void OpenInAppStore() => BrowserOpen("https://steampp.net/");
void StartUpdate()
{
if (IsSupportedServerDistribution)
{
DownloadUpdate();
}
else
{
OpenInAppStore();
}
}
}
}
@@ -186,10 +186,10 @@ namespace System.Application.UI.Views
{
void OnReport()
{
progressBar1.Value = (int)MathF.Floor(v * progressBar1.Maximum);
progressBar1.Value = (int)MathF.Floor(v * 100);
}
Invoke((Action)OnReport);
}));
}), maxProgress: 100f);
Invoke((Action)(() =>
{
button3.Enabled = true;