mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-28 14:08:16 +08:00
AppUpdate
This commit is contained in:
@@ -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);
|
||||
|
||||
+11
-6
@@ -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()
|
||||
|
||||
+6
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Generated
+36
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user