mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Compare commits
7 Commits
feat/versi
...
revert/qr_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a845dff6ee | ||
|
|
ee99d0b665 | ||
|
|
72b62aa9c6 | ||
|
|
6b031e1866 | ||
|
|
59c03c7f3b | ||
|
|
c03a96b44f | ||
|
|
d5a97903d3 |
@@ -5,6 +5,9 @@ using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
|
||||
using Snap.Hutao.Core.IO;
|
||||
using Snap.Hutao.Core.IO.Hashing;
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using Snap.Hutao.ViewModel.Guide;
|
||||
using Snap.Hutao.Web.Request.Builder;
|
||||
using Snap.Hutao.Web.Request.Builder.Abstraction;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Frozen;
|
||||
using System.IO;
|
||||
@@ -36,6 +39,7 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
||||
private readonly ConcurrentDictionary<string, Task> concurrentTasks = new();
|
||||
|
||||
private readonly IHttpClientFactory httpClientFactory;
|
||||
private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory;
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly ILogger<ImageCache> logger;
|
||||
|
||||
@@ -169,38 +173,49 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
||||
HttpClient httpClient = httpClientFactory.CreateClient(nameof(ImageCache));
|
||||
while (retryCount < 3)
|
||||
{
|
||||
using (HttpResponseMessage message = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
|
||||
{
|
||||
if (message.RequestMessage is { RequestUri: { } target } && target != uri)
|
||||
{
|
||||
logger.LogDebug("The Request '{Source}' has been redirected to '{Target}'", uri, target);
|
||||
}
|
||||
HttpRequestMessageBuilder requestMessageBuilder = httpRequestMessageBuilderFactory
|
||||
.Create()
|
||||
.SetRequestUri(uri)
|
||||
|
||||
if (message.IsSuccessStatusCode)
|
||||
// These headers are only available for our own api
|
||||
.SetStaticResourceControlHeadersIf(uri.Host.Contains("api.snapgenshin.com", StringComparison.OrdinalIgnoreCase))
|
||||
.Get();
|
||||
|
||||
using (HttpRequestMessage requestMessage = requestMessageBuilder.HttpRequestMessage)
|
||||
{
|
||||
using (HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
|
||||
{
|
||||
using (Stream httpStream = await message.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
if (responseMessage.RequestMessage is { RequestUri: { } target } && target != uri)
|
||||
{
|
||||
using (FileStream fileStream = File.Create(baseFile))
|
||||
logger.LogDebug("The Request '{Source}' has been redirected to '{Target}'", uri, target);
|
||||
}
|
||||
|
||||
if (responseMessage.IsSuccessStatusCode)
|
||||
{
|
||||
using (Stream httpStream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
await httpStream.CopyToAsync(fileStream).ConfigureAwait(false);
|
||||
return;
|
||||
using (FileStream fileStream = File.Create(baseFile))
|
||||
{
|
||||
await httpStream.CopyToAsync(fileStream).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (message.StatusCode)
|
||||
{
|
||||
case HttpStatusCode.TooManyRequests:
|
||||
{
|
||||
retryCount++;
|
||||
TimeSpan delay = message.Headers.RetryAfter?.Delta ?? retryCountToDelay[retryCount];
|
||||
logger.LogInformation("Retry download '{Uri}' after {Delay}.", uri, delay);
|
||||
await Task.Delay(delay).ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
switch (responseMessage.StatusCode)
|
||||
{
|
||||
case HttpStatusCode.TooManyRequests:
|
||||
{
|
||||
retryCount++;
|
||||
TimeSpan delay = responseMessage.Headers.RetryAfter?.Delta ?? retryCountToDelay[retryCount];
|
||||
logger.LogInformation("Retry download '{Uri}' after {Delay}.", uri, delay);
|
||||
await Task.Delay(delay).ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ internal static class SettingKeys
|
||||
public const string DataFolderPath = "DataFolderPath";
|
||||
public const string Major1Minor10Revision0GuideState = "Major1Minor10Revision0GuideState1";
|
||||
public const string StaticResourceImageQuality = "StaticResourceImageQuality";
|
||||
public const string StaticResourceUseTrimmedArchive = "StaticResourceUseTrimmedArchive";
|
||||
public const string StaticResourceImageArchive = "StaticResourceImageArchive";
|
||||
public const string HotKeyMouseClickRepeatForever = "HotKeyMouseClickRepeatForever";
|
||||
public const string IsAllocConsoleDebugModeEnabled = "IsAllocConsoleDebugModeEnabled2";
|
||||
#endregion
|
||||
|
||||
@@ -14,10 +14,10 @@ namespace Snap.Hutao;
|
||||
internal sealed partial class GuideWindow : Window, IWindowOptionsSource, IMinMaxInfoHandler
|
||||
{
|
||||
private const int MinWidth = 1000;
|
||||
private const int MinHeight = 600;
|
||||
private const int MinHeight = 650;
|
||||
|
||||
private const int MaxWidth = 1200;
|
||||
private const int MaxHeight = 750;
|
||||
private const int MaxHeight = 800;
|
||||
|
||||
private readonly WindowOptions windowOptions;
|
||||
|
||||
|
||||
@@ -1382,6 +1382,9 @@
|
||||
<data name="ViewGachaLogHeader" xml:space="preserve">
|
||||
<value>祈愿记录</value>
|
||||
</data>
|
||||
<data name="ViewGuideStaticResourceDownloadSize" xml:space="preserve">
|
||||
<value>预计下载大小:{0}</value>
|
||||
</data>
|
||||
<data name="ViewGuideStepAgreementIHaveReadText" xml:space="preserve">
|
||||
<value>我已阅读并同意</value>
|
||||
</data>
|
||||
@@ -1440,10 +1443,10 @@
|
||||
<value>图片资源包体</value>
|
||||
</data>
|
||||
<data name="ViewGuideStepStaticResourceSettingMinimumOff" xml:space="preserve">
|
||||
<value>全部资源(节省 0% 磁盘空间占用)</value>
|
||||
<value>完整包体</value>
|
||||
</data>
|
||||
<data name="ViewGuideStepStaticResourceSettingMinimumOn" xml:space="preserve">
|
||||
<value>部分资源(节省 13.5% 磁盘空间占用)</value>
|
||||
<value>精简包体</value>
|
||||
</data>
|
||||
<data name="ViewGuideStepStaticResourceSettingQualityHeader" xml:space="preserve">
|
||||
<value>图片资源质量</value>
|
||||
@@ -1638,10 +1641,10 @@
|
||||
<value>下载资源文件中,请稍候</value>
|
||||
</data>
|
||||
<data name="ViewModelGuideStaticResourceQualityHigh" xml:space="preserve">
|
||||
<value>高质量(节省 72.8% 磁盘空间占用)</value>
|
||||
<value>高质量</value>
|
||||
</data>
|
||||
<data name="ViewModelGuideStaticResourceQualityRaw" xml:space="preserve">
|
||||
<value>原图(节省 0% 磁盘空间占用)</value>
|
||||
<value>原图</value>
|
||||
</data>
|
||||
<data name="ViewModelHutaoPassportEmailNotValidHint" xml:space="preserve">
|
||||
<value>请输入正确的邮箱</value>
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<SelfContained>true</SelfContained>
|
||||
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
|
||||
<WindowsAppSdkUndockedRegFreeWinRTInitialize>false</WindowsAppSdkUndockedRegFreeWinRTInitialize>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -303,8 +305,8 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.TokenizingTextBox" Version="8.0.240109" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.240109" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.3">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@@ -319,7 +321,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.8.8" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.3233" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240311000" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240404000" />
|
||||
<PackageReference Include="QRCoder" Version="1.4.3" />
|
||||
<PackageReference Include="Snap.Discord.GameSDK" Version="1.6.0" />
|
||||
<PackageReference Include="Snap.Hutao.Deployment.Runtime" Version="1.16.0">
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:shc="using:Snap.Hutao.Control"
|
||||
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
xmlns:shvg="using:Snap.Hutao.ViewModel.Guide"
|
||||
@@ -224,10 +223,14 @@
|
||||
ItemsSource="{Binding StaticResourceOptions.ImageQualities}"
|
||||
SelectedItem="{Binding StaticResourceOptions.ImageQuality, Mode=TwoWay}"/>
|
||||
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{shcm:ResourceString Name=ViewGuideStepStaticResourceSettingMinimumHeader}"/>
|
||||
<ToggleSwitch
|
||||
IsOn="{Binding StaticResourceOptions.UseTrimmedArchive, Mode=TwoWay}"
|
||||
OffContent="{shcm:ResourceString Name=ViewGuideStepStaticResourceSettingMinimumOff}"
|
||||
OnContent="{shcm:ResourceString Name=ViewGuideStepStaticResourceSettingMinimumOn}"/>
|
||||
<ListView
|
||||
MinWidth="320"
|
||||
Margin="0,8,0,32"
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding StaticResourceOptions.ImageArchives}"
|
||||
SelectedItem="{Binding StaticResourceOptions.ImageArchive, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Margin="0,16,0,0" Text="{Binding StaticResourceOptions.SizeInformationText, Mode=OneWay}"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock
|
||||
@@ -266,12 +269,20 @@
|
||||
HorizontalAlignment="Center"
|
||||
IsHitTestVisible="False"
|
||||
SelectedIndex="{Binding State, Mode=TwoWay}">
|
||||
<!--
|
||||
<cwc:SegmentedItem Content="{shcm:ResourceString Name=ViewGuideStepLanguage}" Icon="{shcm:FontIcon Glyph=}"/>
|
||||
<cwc:SegmentedItem Content="{shcm:ResourceString Name=ViewGuideStepDocument}" Icon="{shcm:FontIcon Glyph=}"/>
|
||||
<cwc:SegmentedItem Content="{shcm:ResourceString Name=ViewGuideStepEnvironment}" Icon="{shcm:FontIcon Glyph=}"/>
|
||||
<cwc:SegmentedItem Content="{shcm:ResourceString Name=ViewGuideStepCommonSetting}" Icon="{shcm:FontIcon Glyph=}"/>
|
||||
<cwc:SegmentedItem Content="{shcm:ResourceString Name=ViewGuideStepStaticResourceSetting}" Icon="{shcm:FontIcon Glyph=}"/>
|
||||
<cwc:SegmentedItem Content="{shcm:ResourceString Name=ViewGuideStepStaticResource}" Icon="{shcm:FontIcon Glyph=}"/>
|
||||
-->
|
||||
<cwc:SegmentedItem Icon="{shcm:FontIcon Glyph=}"/>
|
||||
<cwc:SegmentedItem Icon="{shcm:FontIcon Glyph=}"/>
|
||||
<cwc:SegmentedItem Icon="{shcm:FontIcon Glyph=}"/>
|
||||
<cwc:SegmentedItem Icon="{shcm:FontIcon Glyph=}"/>
|
||||
<cwc:SegmentedItem Icon="{shcm:FontIcon Glyph=}"/>
|
||||
<cwc:SegmentedItem Icon="{shcm:FontIcon Glyph=}"/>
|
||||
</cwc:Segmented>
|
||||
<Button
|
||||
Command="{Binding NextOrCompleteCommand}"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
using Snap.Hutao.ViewModel.Guide;
|
||||
|
||||
namespace Snap.Hutao.View.Guide;
|
||||
@@ -14,6 +15,6 @@ internal sealed partial class GuideView : UserControl
|
||||
public GuideView()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = Ioc.Default.GetRequiredService<GuideViewModel>();
|
||||
DataContext = this.ServiceProvider().GetRequiredService<GuideViewModel>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ using Snap.Hutao.Core.Setting;
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Service;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
using Snap.Hutao.Web.Hutao;
|
||||
using Snap.Hutao.Web.Hutao.Response;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -164,6 +166,19 @@ internal sealed partial class GuideViewModel : Abstraction.ViewModel
|
||||
set => SetProperty(ref downloadSummaries, value);
|
||||
}
|
||||
|
||||
protected override async ValueTask<bool> InitializeUIAsync()
|
||||
{
|
||||
HutaoInfrastructureClient hutaoInfrastructureClient = serviceProvider.GetRequiredService<HutaoInfrastructureClient>();
|
||||
HutaoResponse<StaticResourceSizeInformation> response = await hutaoInfrastructureClient.GetStaticSizeAsync().ConfigureAwait(false);
|
||||
if (response.IsOk())
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
StaticResourceOptions.SizeInformation = response.Data;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[Command("NextOrCompleteCommand")]
|
||||
private void NextOrComplete()
|
||||
{
|
||||
|
||||
@@ -46,31 +46,31 @@ internal static class StaticResource
|
||||
|
||||
private static readonly ApplicationDataCompositeValue LatestResourceVersionMap = new()
|
||||
{
|
||||
{ "AchievementIcon", 1 },
|
||||
{ "AvatarCard", 1 },
|
||||
{ "AvatarIcon", 4 },
|
||||
{ "Bg", 2 },
|
||||
{ "ChapterIcon", 2 },
|
||||
{ "AchievementIcon", 2 },
|
||||
{ "AvatarCard", 2 },
|
||||
{ "AvatarIcon", 5 },
|
||||
{ "Bg", 3 },
|
||||
{ "ChapterIcon", 3 },
|
||||
{ "CodexMonster", 0 },
|
||||
{ "Costume", 1 },
|
||||
{ "EmotionIcon", 2 },
|
||||
{ "EquipIcon", 3 },
|
||||
{ "GachaAvatarIcon", 3 },
|
||||
{ "GachaAvatarImg", 3 },
|
||||
{ "GachaEquipIcon", 3 },
|
||||
{ "Costume", 2 },
|
||||
{ "EmotionIcon", 3 },
|
||||
{ "EquipIcon", 4 },
|
||||
{ "GachaAvatarIcon", 4 },
|
||||
{ "GachaAvatarImg", 4 },
|
||||
{ "GachaEquipIcon", 4 },
|
||||
{ "GcgCharAvatarIcon", 0 },
|
||||
{ "IconElement", 2 },
|
||||
{ "ItemIcon", 3 },
|
||||
{ "LoadingPic", 1 },
|
||||
{ "MonsterIcon", 2 },
|
||||
{ "MonsterSmallIcon", 1 },
|
||||
{ "NameCardIcon", 2 },
|
||||
{ "NameCardPic", 3 },
|
||||
{ "IconElement", 3 },
|
||||
{ "ItemIcon", 4 },
|
||||
{ "LoadingPic", 2 },
|
||||
{ "MonsterIcon", 3 },
|
||||
{ "MonsterSmallIcon", 2 },
|
||||
{ "NameCardIcon", 3 },
|
||||
{ "NameCardPic", 4 },
|
||||
{ "NameCardPicAlpha", 0 },
|
||||
{ "Property", 1 },
|
||||
{ "RelicIcon", 3 },
|
||||
{ "Skill", 3 },
|
||||
{ "Talent", 3 },
|
||||
{ "Property", 2 },
|
||||
{ "RelicIcon", 4 },
|
||||
{ "Skill", 4 },
|
||||
{ "Talent", 4 },
|
||||
};
|
||||
|
||||
public static void FulfillAll()
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.ViewModel.Guide;
|
||||
|
||||
[Localization]
|
||||
internal enum StaticResourceArchive
|
||||
{
|
||||
[LocalizationKey(nameof(SH.ViewGuideStepStaticResourceSettingMinimumOff))]
|
||||
Full,
|
||||
|
||||
[LocalizationKey(nameof(SH.ViewGuideStepStaticResourceSettingMinimumOn))]
|
||||
Minimum,
|
||||
}
|
||||
@@ -15,6 +15,12 @@ internal static class StaticResourceHttpHeaderBuilderExtension
|
||||
{
|
||||
return builder
|
||||
.SetHeader("x-quality", $"{UnsafeLocalSetting.Get(SettingKeys.StaticResourceImageQuality, StaticResourceQuality.Raw)}")
|
||||
.SetHeader("x-minimum", $"{LocalSetting.Get(SettingKeys.StaticResourceUseTrimmedArchive, false)}");
|
||||
.SetHeader("x-archive", $"{UnsafeLocalSetting.Get(SettingKeys.StaticResourceImageArchive, StaticResourceArchive.Full)}");
|
||||
}
|
||||
|
||||
public static TBuilder SetStaticResourceControlHeadersIf<TBuilder>(this TBuilder builder, bool condition)
|
||||
where TBuilder : IHttpHeadersBuilder<HttpHeaders>
|
||||
{
|
||||
return condition ? builder.SetStaticResourceControlHeaders() : builder;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,82 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Common;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Snap.Hutao.Core.Setting;
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Web.Hutao;
|
||||
|
||||
namespace Snap.Hutao.ViewModel.Guide;
|
||||
|
||||
[Injection(InjectAs.Singleton)]
|
||||
internal sealed class StaticResourceOptions
|
||||
internal sealed class StaticResourceOptions : ObservableObject
|
||||
{
|
||||
private readonly List<NameValue<StaticResourceQuality>> imageQualities = CollectionsNameValue.FromEnum<StaticResourceQuality>(q => q.GetLocalizedDescription());
|
||||
private readonly List<NameValue<StaticResourceArchive>> imageArchives = CollectionsNameValue.FromEnum<StaticResourceArchive>(a => a.GetLocalizedDescription());
|
||||
|
||||
private NameValue<StaticResourceQuality>? imageQuality;
|
||||
private NameValue<StaticResourceArchive>? imageArchive;
|
||||
private string? sizeInformationText;
|
||||
|
||||
public StaticResourceOptions()
|
||||
{
|
||||
ImageQuality = ImageQualities.First(q => q.Value == UnsafeLocalSetting.Get(SettingKeys.StaticResourceImageQuality, StaticResourceQuality.Raw));
|
||||
}
|
||||
private StaticResourceSizeInformation? sizeInformation;
|
||||
|
||||
public List<NameValue<StaticResourceQuality>> ImageQualities { get => imageQualities; }
|
||||
|
||||
public NameValue<StaticResourceQuality>? ImageQuality
|
||||
{
|
||||
get => imageQuality;
|
||||
get => imageQuality ??= ImageQualities.First(q => q.Value == UnsafeLocalSetting.Get(SettingKeys.StaticResourceImageQuality, StaticResourceQuality.Raw));
|
||||
set
|
||||
{
|
||||
if (value is not null)
|
||||
if (SetProperty(ref imageQuality, value) && value is not null)
|
||||
{
|
||||
imageQuality = value;
|
||||
UnsafeLocalSetting.Set(SettingKeys.StaticResourceImageQuality, value.Value);
|
||||
UpdateSizeInformationText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseTrimmedArchive
|
||||
public List<NameValue<StaticResourceArchive>> ImageArchives { get => imageArchives; }
|
||||
|
||||
public NameValue<StaticResourceArchive>? ImageArchive
|
||||
{
|
||||
get => LocalSetting.Get(SettingKeys.StaticResourceUseTrimmedArchive, false);
|
||||
set => LocalSetting.Set(SettingKeys.StaticResourceUseTrimmedArchive, value);
|
||||
get => imageArchive ??= ImageArchives.First(a => a.Value == UnsafeLocalSetting.Get(SettingKeys.StaticResourceImageArchive, StaticResourceArchive.Full));
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref imageArchive, value) && value is not null)
|
||||
{
|
||||
UnsafeLocalSetting.Set(SettingKeys.StaticResourceImageArchive, value.Value);
|
||||
UpdateSizeInformationText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public StaticResourceSizeInformation? SizeInformation
|
||||
{
|
||||
get => sizeInformation;
|
||||
set
|
||||
{
|
||||
sizeInformation = value;
|
||||
UpdateSizeInformationText();
|
||||
}
|
||||
}
|
||||
|
||||
public string? SizeInformationText { get => sizeInformationText; set => SetProperty(ref sizeInformationText, value); }
|
||||
|
||||
private void UpdateSizeInformationText()
|
||||
{
|
||||
if (SizeInformation is not null)
|
||||
{
|
||||
long result = (ImageQuality?.Value, ImageArchive?.Value) switch
|
||||
{
|
||||
(StaticResourceQuality.Raw, StaticResourceArchive.Full) => SizeInformation.RawFull,
|
||||
(StaticResourceQuality.Raw, StaticResourceArchive.Minimum) => SizeInformation.RawMinimum,
|
||||
(StaticResourceQuality.High, StaticResourceArchive.Full) => SizeInformation.HighFull,
|
||||
(StaticResourceQuality.High, StaticResourceArchive.Minimum) => SizeInformation.HighMinimum,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
SizeInformationText = SH.FormatViewGuideStaticResourceDownloadSize(Converters.ToFileSizeString(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,10 @@ internal sealed partial class PandaClient
|
||||
|
||||
public async ValueTask<Response<UrlWrapper>> QRCodeFetchAsync(CancellationToken token = default)
|
||||
{
|
||||
// Use 12 (zzz) instead of 4 (gi) temporarily to get legacy game token
|
||||
GameLoginRequest options = GameLoginRequest.Create(12, HoyolabOptions.DeviceId40);
|
||||
GameLoginRequest options = GameLoginRequest.Create(4, HoyolabOptions.DeviceId40);
|
||||
|
||||
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
|
||||
.SetRequestUri(ApiEndpoints.QrCodeFetch)
|
||||
.SetHeader("x-rpc-device_id", HoyolabOptions.DeviceId40)
|
||||
.PostJson(options);
|
||||
|
||||
Response<UrlWrapper>? resp = await builder
|
||||
@@ -36,11 +34,10 @@ internal sealed partial class PandaClient
|
||||
|
||||
public async ValueTask<Response<GameLoginResult>> QRCodeQueryAsync(string ticket, CancellationToken token = default)
|
||||
{
|
||||
GameLoginRequest options = GameLoginRequest.Create(12, HoyolabOptions.DeviceId40, ticket);
|
||||
GameLoginRequest options = GameLoginRequest.Create(4, HoyolabOptions.DeviceId40, ticket);
|
||||
|
||||
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
|
||||
.SetRequestUri(ApiEndpoints.QrCodeQuery)
|
||||
.SetHeader("x-rpc-device_id", HoyolabOptions.DeviceId40)
|
||||
.PostJson(options);
|
||||
|
||||
Response<GameLoginResult>? resp = await builder
|
||||
|
||||
@@ -79,7 +79,6 @@ internal sealed partial class PassportClient2
|
||||
|
||||
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
|
||||
.SetRequestUri(ApiEndpoints.AccountGetSTokenByGameToken)
|
||||
.SetHeader("x-rpc-device_id", HoyolabOptions.DeviceId40)
|
||||
.PostJson(data);
|
||||
|
||||
Response<LoginResult>? resp = await builder
|
||||
|
||||
@@ -17,6 +17,16 @@ internal sealed partial class HutaoInfrastructureClient
|
||||
private readonly ILogger<HutaoInfrastructureClient> logger;
|
||||
private readonly HttpClient httpClient;
|
||||
|
||||
public async ValueTask<HutaoResponse<StaticResourceSizeInformation>> GetStaticSizeAsync(CancellationToken token = default)
|
||||
{
|
||||
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
|
||||
.SetRequestUri(HutaoEndpoints.StaticSize)
|
||||
.Get();
|
||||
|
||||
HutaoResponse<StaticResourceSizeInformation>? resp = await builder.TryCatchSendAsync<HutaoResponse<StaticResourceSizeInformation>>(httpClient, logger, token).ConfigureAwait(false);
|
||||
return Web.Response.Response.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
public async ValueTask<HutaoResponse<IPInformation>> GetIPInformationAsync(CancellationToken token = default)
|
||||
{
|
||||
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao;
|
||||
|
||||
internal sealed partial class StaticResourceSizeInformation
|
||||
{
|
||||
[JsonPropertyName("raw_full")]
|
||||
public long RawFull { get; set; }
|
||||
|
||||
[JsonPropertyName("raw_minimum")]
|
||||
public long RawMinimum { get; set; }
|
||||
|
||||
[JsonPropertyName("tiny_full")]
|
||||
public long HighFull { get; set; }
|
||||
|
||||
[JsonPropertyName("tiny_minimum")]
|
||||
public long HighMinimum { get; set; }
|
||||
}
|
||||
@@ -270,6 +270,8 @@ internal static class HutaoEndpoints
|
||||
{
|
||||
return $"{ApiSnapGenshinStaticZip}/{fileName}.zip";
|
||||
}
|
||||
|
||||
public const string StaticSize = $"{ApiSnapGenshin}/static/size";
|
||||
#endregion
|
||||
|
||||
#region Wallpaper
|
||||
|
||||
Reference in New Issue
Block a user