This commit is contained in:
Aigio Liu
2021-08-01 19:57:29 +08:00
parent 003df684bd
commit 953f8d6522
17 changed files with 237 additions and 135 deletions
+1
View File
@@ -160,6 +160,7 @@ Read what we [milestones](https://github.com/SteamTools-Team/SteamTools/mileston
* [ZXing.Net](https://github.com/micjahn/ZXing.Net)
* [ZXing.Net.Mobile](https://github.com/Redth/ZXing.Net.Mobile)
* [QRCoder](https://github.com/codebude/QRCoder)
* [SharpCompress](https://github.com/adamhathcock/sharpcompress)
* [React](https://github.com/facebook/react)
* [Ant Design](https://github.com/ant-design/ant-design)
* [Ant Design Blazor](https://github.com/ant-design-blazor/ant-design-blazor)
+1
View File
@@ -172,6 +172,7 @@
* [ZXing.Net](https://github.com/micjahn/ZXing.Net)
* [ZXing.Net.Mobile](https://github.com/Redth/ZXing.Net.Mobile)
* [QRCoder](https://github.com/codebude/QRCoder)
* [SharpCompress](https://github.com/adamhathcock/sharpcompress)
* [React](https://github.com/facebook/react)
* [Ant Design](https://github.com/ant-design/ant-design)
* [Ant Design Blazor](https://github.com/ant-design-blazor/ant-design-blazor)
+2 -1
View File
@@ -17,7 +17,8 @@
17. 改进 开机自启动现仅对当前用户生效
18. 改进 程序根目录结构,相较于上一个版本移除了 Bin 文件夹,减少 dll 文件数量
19. 改进 优化了发行版本压缩包体积(移除了 CEF 模块,对于需要使用第三方账号快速登录功能可使用上一个版本的压缩包中 \Bin\CEF 将这个文件夹拷贝到 \CEF 中)
20. Android/macOS/Linux 版现已开启 Beta/Alpha 测试,可从 GitHub/Gitee 上下载
20. 改进 现已编译为 ReadyToRun (R2R) 格式,这将改进应用程序的启动时间和延迟(仅 Windows 版本)
21. Android/macOS/Linux 版现已开启 Beta/Alpha 测试,可从 GitHub/Gitee 上下载
***
@@ -2,7 +2,9 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using static System.Properties.ThisAssembly;
#pragma warning disable SYSLIB0025 // 类型或成员已过时
[assembly: SuppressIldasm]
#pragma warning restore SYSLIB0025 // 类型或成员已过时
[assembly: AssemblyTitle(AssemblyTrademark)]
[assembly: AssemblyTrademark(AssemblyTrademark)]
[assembly: AssemblyDescription(AssemblyDescription)]
@@ -8,15 +8,13 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<Configuration>Release</Configuration>
<PublishDir>bin\Release\Publish\win-x64</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<SelfContained>true</SelfContained>
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
<PublishReadyToRun>true</PublishReadyToRun>
<PublishReadyToRunUseCrossgen2>false</PublishReadyToRunUseCrossgen2>
<PublishReadyToRunComposite>false</PublishReadyToRunComposite>
<Platform>Any CPU</Platform>
<TargetFramework>net6.0</TargetFramework>
<PublishSingleFile>false</PublishSingleFile>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>false</PublishTrimmed>
<EnableCompressionInSingleFile>false</EnableCompressionInSingleFile>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
</Project>
@@ -38,6 +38,7 @@
<PackageReference Include="Gameloop.Vdf" Version="0.6.1" />
<PackageReference Include="NLog" Version="4.7.10" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.7.3" />
<PackageReference Include="SharpCompress" Version="0.28.3" />
<PackageReference Include="SharpZipLib" Version="1.3.2" />
<PackageReference Include="StatefulModel.Standard" Version="0.1.0" />
<!--<PackageReference Include="Titanium.Web.Proxy" Version="3.1.1344" />-->
@@ -23,7 +23,7 @@ namespace System.Application.Services.Implementation
/// </summary>
protected abstract void OnExit();
protected override void OverwriteUpgrade(string value, bool isIncrement)
protected override void OverwriteUpgrade(string value, bool isIncrement, AppDownloadType downloadType)
{
if (isIncrement) // 增量更新
{
@@ -38,7 +38,19 @@ namespace System.Application.Services.Implementation
Directory.Delete(dirPath, true);
}
if (TarGZipHelper.Unpack(value, dirPath, progress: new Progress<float>(OnReportDecompressing), maxProgress: MaxProgressValue))
var isOK = downloadType switch
{
AppDownloadType.Compressed_GZip
=> TarGZipHelper.Unpack(value, dirPath,
progress: new Progress<float>(OnReportDecompressing),
maxProgress: MaxProgressValue),
AppDownloadType.Compressed_7z
=> SevenZipHelper.Unpack(value, dirPath,
progress: new Progress<float>(OnReportDecompressing),
maxProgress: MaxProgressValue),
_ => throw new NotSupportedException(),
};
if (isOK)
{
OnReport(MaxProgressValue);
IOPath.FileTryDelete(value);
+80
View File
@@ -0,0 +1,80 @@
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Common;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace System.Application
{
public static class SevenZipHelper
{
/// <summary>
/// 解压压缩包文件
/// </summary>
/// <param name="filePath">要解压的压缩包文件路径</param>
/// <param name="dirPath">要解压的文件夹路径,文件夹必须不存在</param>
/// <param name="progress">进度值监听</param>
/// <param name="maxProgress"></param>
/// <returns></returns>
public static bool Unpack(string filePath, string dirPath,
IProgress<float>? progress = null,
float maxProgress = 100f)
{
if (!File.Exists(filePath)) return false;
if (Directory.Exists(dirPath)) return false;
using var fs = File.OpenRead(filePath);
float length = fs.Length;
var isFinish = false;
CancellationTokenSource? cts = null;
async void ProgressMonitor()
{
try
{
while (!isFinish)
{
var value = fs.Position / length * maxProgress;
progress!.Report(value);
await Task.Delay(200, cts.Token);
}
}
catch (OperationCanceledException)
{
}
}
Directory.CreateDirectory(dirPath);
using var archive = SevenZipArchive.Open(fs);
var hasProgress = progress != null;
if (hasProgress)
{
cts = new();
try
{
Task.Factory.StartNew(ProgressMonitor, cts.Token);
}
catch (OperationCanceledException)
{
}
}
var files = archive.Entries.Where(entry => !entry.IsDirectory).ToArray();
for (int i = 0; i < files.Length; i++)
{
var file = files[i];
file.WriteToDirectory(dirPath, new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
isFinish = true;
if (hasProgress)
{
cts!.Cancel();
progress!.Report(maxProgress);
}
return true;
}
}
}
+30 -7
View File
@@ -1,8 +1,9 @@
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip.Compression;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace System.Application
@@ -75,23 +76,45 @@ namespace System.Application
// https://github.com/icsharpcode/SharpZipLib/blob/v1.3.1/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs#L542
float length = fs.Length;
var isFinish = false;
CancellationTokenSource? cts = null;
async void ProgressMonitor()
{
while (!isFinish)
try
{
while (!isFinish)
{
var value = fs.Position / length * maxProgress;
progress!.Report(value);
await Task.Delay(200, cts.Token);
}
}
catch (OperationCanceledException)
{
var value = fs.Position / length * maxProgress;
progress.Report(value);
await Task.Delay(200);
}
}
Directory.CreateDirectory(dirPath);
using var s = new GZipInputStream(fs);
using var archive = TarArchive.CreateInputTarArchive(s, Encoding.UTF8);
if (progressMessage != null) archive.ProgressMessageEvent += progressMessage;
if (progress != null) Task.Factory.StartNew(ProgressMonitor);
var hasProgress = progress != null;
if (hasProgress)
{
cts = new();
try
{
Task.Factory.StartNew(ProgressMonitor, cts.Token);
}
catch (OperationCanceledException)
{
}
}
archive.ExtractContents(dirPath);
isFinish = true;
progress?.Report(maxProgress);
if (hasProgress)
{
cts!.Cancel();
progress!.Report(maxProgress);
}
return true;
}
}
+1 -1
View File
@@ -3151,7 +3151,7 @@ namespace System.Application.UI.Resx {
}
/// <summary>
/// 查找类似 *需重启生效 的本地化字符串。
/// 查找类似 *需重启软件后生效 的本地化字符串。
/// </summary>
public static string Settings_RestartEffective {
get {
@@ -1488,7 +1488,7 @@
<value>使用硬件加速</value>
</data>
<data name="Settings_RestartEffective" xml:space="preserve">
<value>*需重启生效</value>
<value>*需重启软件后生效</value>
</data>
<data name="Settings_General_UpdateChannel" xml:space="preserve">
<value>下载更新渠道</value>
@@ -1502,4 +1502,4 @@
<data name="BrowseBaseDirectory" xml:space="preserve">
<value>浏览基目录</value>
</data>
</root>
</root>
+13 -4
View File
@@ -4,6 +4,7 @@ using System.Application.UI.ViewModels;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Properties;
using System.Reactive.Linq;
using AppRes = System.Application.UI.Resx.AppResources;
#if __MOBILE__
@@ -30,7 +31,7 @@ namespace System.Application.UI.Resx
static R()
{
DefaultCurrentUICulture = CultureInfo.CurrentUICulture;
Languages = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
var languagesDict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "", "Auto" },
{ "zh-Hans", "Chinese(Simplified)" },
@@ -39,9 +40,17 @@ namespace System.Application.UI.Resx
{ "ko", "Koreana" },
{ "ja", "Japanese" },
{ "ru", "Russian" },
//{ "es", "Spanish" },
//{ "it", "Italian" },
}.ToList();
{ "es", "Spanish" },
{ "it", "Italian" },
};
#if !DEBUG
if (new Version(ThisAssembly.Version) < new Version(2, 5))
{
languagesDict.Remove("es");
languagesDict.Remove("it");
}
#endif
Languages = languagesDict.ToList();
SteamLanguages = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "zh-CN", "schinese" },
@@ -75,7 +75,19 @@ namespace System.Application.UI.ViewModels
AddTabItem<SteamAccountPageViewModel>();
AddTabItem<GameListPageViewModel>();
AddTabItem<LocalAuthPageViewModel>();
AddTabItem<ArchiSteamFarmPlusPageViewModel>();
var isVersion_2_5_OR_GREATER =
#if DEBUG
true;
#else
new Version(ThisAssembly.Version) < new Version(2, 5);
#endif
if (isVersion_2_5_OR_GREATER)
{
AddTabItem<ArchiSteamFarmPlusPageViewModel>();
}
//AddTabItem<SteamIdlePageViewModel>();
if (DI.Platform == Platform.Windows)
AddTabItem<GameRelatedPageViewModel>();
Binary file not shown.
@@ -2,8 +2,8 @@ using Microsoft.Extensions.Options;
using ReactiveUI;
using System.Application.Models;
using System.Application.Properties;
using System.IO;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
@@ -254,7 +254,15 @@ namespace System.Application.Services.Implementation
goto end;
}
if (newVersionInfo.CurrentAllFiles.Any_Nullable() &&
var isAndroid = DI.Platform == Platform.Android;
var isDesktop = DI.Platform == Platform.Windows || DI.Platform == Platform.Linux || DI.IsmacOS;
if (!isAndroid && !isDesktop)
{
OpenInAppStore();
goto end;
}
if (!isAndroid && newVersionInfo.CurrentAllFiles.Any_Nullable() &&
newVersionInfo.CurrentAllFiles.All(x => x.HasValue()) &&
newVersionInfo.AllFiles.Any_Nullable() &&
newVersionInfo.AllFiles.All(x => x.HasValue())) // 增量更新 v2
@@ -385,96 +393,28 @@ namespace System.Application.Services.Implementation
OnReport(MaxProgressValue);
OverwriteUpgrade(packDirPath, isIncrement: true);
}
//if (newVersionInfo!.IncrementalUpdate.Any_Nullable()) // 增量更新 v1
//{
// if (Path.DirectorySeparatorChar != '\\')
// {
// foreach (var item in newVersionInfo.IncrementalUpdate!)
// {
// item.FileRelativePath =
// item.FileRelativePath?.Replace('\\', Path.DirectorySeparatorChar);
// }
// }
// var packDirName = GetPackName(newVersionInfo, isDirOrFile: false);
// var packDirPath = Path.Combine(GetPackCacheDirPath(!isSupportedResume), packDirName);
// var incrementalUpdate = newVersionInfo.IncrementalUpdate.ToDictionary(x => x, x => packDirPath + Path.DirectorySeparatorChar + x.FileRelativePath);
// if (Directory.Exists(packDirPath))
// {
// foreach (var item in newVersionInfo.IncrementalUpdate!)
// {
// var filePath = incrementalUpdate[item];
// var fileInfo = new FileInfo(filePath);
// if (fileInfo.Exists)
// {
// if (fileInfo.Length == item.Length)
// {
// using var fileStream = fileInfo.OpenRead();
// var sha256 = Hashs.String.SHA256(fileStream);
// if (sha256 == item.SHA256)
// {
// incrementalUpdate.Remove(item);
// continue;
// }
// }
// fileInfo.Delete();
// }
// }
// }
// int i = 1;
// void OnReportDownloading3_(float value) => OnReportDownloading3(value, i, incrementalUpdate.Count);
// OnReportDownloading3_(0f);
// foreach (var item in incrementalUpdate)
// {
// var fileName = item.Value;
// var cacheFileName = fileName + FileExDownloadCache;
// var requestUri = GetSingleFileUrl(item.Key.FileId!);
// var rsp = await client.Download(
// isAnonymous: true,
// requestUri: requestUri,
// cacheFileName,
// null);
// if (rsp.IsSuccess)
// {
// File.Move(cacheFileName, fileName);
// if (!UpdatePackVerification(fileName, item.Key.SHA256!, i, incrementalUpdate.Count))
// {
// Fail(SR.UpdatePackVerificationFail);
// break;
// }
// }
// else
// {
// Fail(SR.DownloadUpdateFail);
// break;
// }
// i++;
// OnReportDownloading3_(i / (float)incrementalUpdate.Count * MaxProgressValue);
// }
// OnReport(MaxProgressValue);
// OverwriteUpgrade(packDirPath, isIncrement: true);
//}
else // 全量更新
{
if (DI.Platform != Platform.Android) // 全量更新预计仅支持 Android 平台
AppVersionDTO.Download? download = null;
if (newVersionInfo.Downloads != null)
{
OpenInAppStore();
goto end;
if (isAndroid)
{
download = newVersionInfo.Downloads.FirstOrDefault(x => x.DownloadType == AppDownloadType.Install);
}
else if (isDesktop)
{
download = newVersionInfo.Downloads.FirstOrDefault(x => x.DownloadType == AppDownloadType.Compressed_7z);
if (download == null)
{
download = newVersionInfo.Downloads.FirstOrDefault(x => x.DownloadType == AppDownloadType.Compressed_GZip);
}
}
else
{
throw new PlatformNotSupportedException();
}
}
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);
@@ -492,22 +432,23 @@ namespace System.Application.Services.Implementation
}
}
string fileEx;
string filePlatform;
string fileArch;
switch (newVersionInfo.Platform)
var fileEx = newVersionInfo.Platform switch
{
case Platform.Android:
fileEx = FileEx.APK;
break;
case Platform.Windows:
case Platform.Linux:
case Platform.Apple:
fileEx = FileEx.TAR_GZ;
break;
default:
Fail(SR.UpdateEnumOutOfRange);
goto end;
Platform.Android => FileEx.APK,
Platform.Windows or Platform.Linux or Platform.Apple => download!.DownloadType switch
{
AppDownloadType.Compressed_GZip => FileEx.TAR_GZ,
AppDownloadType.Compressed_7z => FileEx._7Z,
_ => string.Empty,
},
_ => string.Empty,
};
if (fileEx == string.Empty)
{
Fail(SR.UpdateEnumOutOfRange);
goto end;
}
switch (newVersionInfo.Platform)
{
@@ -535,16 +476,32 @@ namespace System.Application.Services.Implementation
case ArchitectureFlags.Arm64:
fileArch = "arm64";
break;
case ArchitectureFlags.Arm:
fileArch = "arm";
break;
default:
fileArch = ((int)newVersionInfo.SupportedAbis).ToString();
break;
case 0:
case ArchitectureFlags.Arm:
Fail(SR.UpdateEnumOutOfRange);
goto end;
}
var downloadFileName = $"{filePlatform}-{fileArch}_{newVersionInfo.Version}{fileEx}";
var requestUri = GetPackFileUrl(downloadFileName);
string requestUri;
if (string.IsNullOrWhiteSpace(download!.FileIdOrUrl))
{
var downloadFileName = $"{filePlatform}-{fileArch}_{newVersionInfo.Version}{fileEx}";
requestUri = GetPackFileUrl(downloadFileName);
}
else if (IsHttpUrl(download.FileIdOrUrl))
{
requestUri = download.FileIdOrUrl;
}
else
{
requestUri = GetSingleFileUrl(download.FileIdOrUrl!);
}
var cacheFilePath = packFilePath + FileExDownloadCache;
OnReportDownloading(0f);
var rsp = await client.Download(
@@ -559,7 +516,7 @@ namespace System.Application.Services.Implementation
if (UpdatePackVerification(packFilePath, download!.SHA256!)) // (下载文件)哈希验证成功,进行覆盖安装
{
OverwriteUpgrade(packFileName, isIncrement: false);
OverwriteUpgrade(packFileName, isIncrement: false, downloadType: download.DownloadType);
OnReportDownloading(MaxProgressValue);
}
else
@@ -574,7 +531,7 @@ namespace System.Application.Services.Implementation
}
else
{
Fail("The new version compressed package is missing, please contact the administrator.");
OpenInAppStore();
}
}
}
@@ -595,7 +552,8 @@ namespace System.Application.Services.Implementation
/// </summary>
/// <param name="value"></param>
/// <param name="isIncrement"></param>
protected abstract void OverwriteUpgrade(string value, bool isIncrement);
/// <param name="downloadType"></param>
protected abstract void OverwriteUpgrade(string value, bool isIncrement, AppDownloadType downloadType = default);
/// <summary>
/// 在应用商店中打开
@@ -88,12 +88,11 @@ namespace System.Application.Models
public long Length { get; set; }
[MPKey(3)]
public string? FileId { get; set; }
public string? FileIdOrUrl { get; set; }
bool IExplicitHasValue.ExplicitHasValue()
{
return !string.IsNullOrWhiteSpace(SHA256) &&
!string.IsNullOrWhiteSpace(FileId) &&
Length > 0;
}
}
+8 -3
View File
@@ -1,4 +1,4 @@
namespace System.Application
namespace System.Application
{
/// <summary>
/// APP下载类型
@@ -11,8 +11,13 @@
Install,
/// <summary>
/// 压缩包
/// 压缩包(GZip)
/// </summary>
Compressed,
Compressed_GZip,
/// <summary>
/// 压缩包(7z)
/// </summary>
Compressed_7z,
}
}