add documentation client

This commit is contained in:
DismissedLight
2024-01-07 14:49:02 +08:00
parent e9917e788d
commit 1ebcc2fc89
34 changed files with 278 additions and 105 deletions

View File

@@ -48,10 +48,10 @@ internal static class DependencyInjection
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void InitializeCulture(this IServiceProvider serviceProvider)
{
AppOptions appOptions = serviceProvider.GetRequiredService<AppOptions>();
appOptions.PreviousCulture = CultureInfo.CurrentCulture;
CultureOptions cultureOptions = serviceProvider.GetRequiredService<CultureOptions>();
cultureOptions.SystemCulture = CultureInfo.CurrentCulture;
CultureInfo cultureInfo = appOptions.CurrentCulture;
CultureInfo cultureInfo = cultureOptions.CurrentCulture;
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;

View File

@@ -38,8 +38,8 @@ internal static class IocConfiguration
private static void AddDbContextCore(IServiceProvider provider, DbContextOptionsBuilder builder)
{
RuntimeOptions hutaoOptions = provider.GetRequiredService<RuntimeOptions>();
string dbFile = System.IO.Path.Combine(hutaoOptions.DataFolder, "Userdata.db");
RuntimeOptions runtimeOptions = provider.GetRequiredService<RuntimeOptions>();
string dbFile = System.IO.Path.Combine(runtimeOptions.DataFolder, "Userdata.db");
string sqlConnectionString = $"Data Source={dbFile}";
// Temporarily create a context

View File

@@ -29,10 +29,10 @@ internal static partial class IocHttpClientConfiguration
/// <param name="client">配置后的客户端</param>
private static void DefaultConfiguration(IServiceProvider serviceProvider, HttpClient client)
{
RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
RuntimeOptions runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
client.Timeout = Timeout.InfiniteTimeSpan;
client.DefaultRequestHeaders.UserAgent.ParseAdd(hutaoOptions.UserAgent);
client.DefaultRequestHeaders.UserAgent.ParseAdd(runtimeOptions.UserAgent);
}
/// <summary>

View File

@@ -53,10 +53,10 @@ internal sealed class WindowController
private void InitializeCore()
{
RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
RuntimeOptions runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
window.AppWindow.Title = SH.FormatAppNameAndVersion(hutaoOptions.Version);
window.AppWindow.SetIcon(Path.Combine(hutaoOptions.InstalledLocation, "Assets/Logo.ico"));
window.AppWindow.Title = SH.FormatAppNameAndVersion(runtimeOptions.Version);
window.AppWindow.SetIcon(Path.Combine(runtimeOptions.InstalledLocation, "Assets/Logo.ico"));
ExtendsContentIntoTitleBar();
RecoverOrInitWindowSize();

View File

@@ -3,6 +3,7 @@
using Snap.Hutao.Core;
using Snap.Hutao.Core.Abstraction;
using Snap.Hutao.Service;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Web.Hoyolab;
@@ -12,7 +13,7 @@ namespace Snap.Hutao.Model.InterChange.GachaLog;
/// UIGF格式的信息
/// </summary>
[HighQuality]
internal sealed class UIGFInfo : IMappingFrom<UIGFInfo, RuntimeOptions, MetadataOptions, string>
internal sealed class UIGFInfo : IMappingFrom<UIGFInfo, RuntimeOptions, CultureOptions, string>
{
/// <summary>
/// 用户Uid
@@ -65,12 +66,12 @@ internal sealed class UIGFInfo : IMappingFrom<UIGFInfo, RuntimeOptions, Metadata
[JsonPropertyName("region_time_zone")]
public int? RegionTimeZone { get; set; } = default!;
public static UIGFInfo From(RuntimeOptions runtimeOptions, MetadataOptions metadataOptions, string uid)
public static UIGFInfo From(RuntimeOptions runtimeOptions, CultureOptions cultureOptions, string uid)
{
return new()
{
Uid = uid,
Language = metadataOptions.LanguageCode,
Language = cultureOptions.LanguageCode,
ExportTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
ExportApp = SH.AppName,
ExportAppVersion = runtimeOptions.Version.ToString(),

View File

@@ -64,14 +64,14 @@ internal sealed class UIIFInfo
/// <returns>专用 UIGF 信息</returns>
public static UIIFInfo From(IServiceProvider serviceProvider, string uid)
{
RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
RuntimeOptions runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
return new()
{
Uid = uid,
ExportTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
ExportApp = SH.AppName,
ExportAppVersion = hutaoOptions.Version.ToString(),
ExportAppVersion = runtimeOptions.Version.ToString(),
UIIFVersion = UIIF.CurrentVersion,
};
}

View File

@@ -6,7 +6,6 @@ using Snap.Hutao.Model;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Web.Hoyolab;
using System.Globalization;
namespace Snap.Hutao.Service;
@@ -16,7 +15,6 @@ internal sealed partial class AppOptions : DbStoreOptions
{
private bool? isEmptyHistoryWishVisible;
private BackdropType? backdropType;
private CultureInfo? currentCulture;
private Region? region;
private string? geetestCustomCompositeUrl;
@@ -34,14 +32,6 @@ internal sealed partial class AppOptions : DbStoreOptions
set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, value => value.ToStringOrEmpty());
}
public List<NameValue<CultureInfo>> Cultures { get; } = SupportedCultures.Get();
public CultureInfo CurrentCulture
{
get => GetOption(ref currentCulture, SettingEntry.Culture, CultureInfo.GetCultureInfo, CultureInfo.CurrentCulture);
set => SetOption(ref currentCulture, SettingEntry.Culture, value, value => value.Name);
}
public Lazy<List<NameValue<Region>>> LazyRegions { get; } = new(KnownRegions.Get);
public Region Region
@@ -55,6 +45,4 @@ internal sealed partial class AppOptions : DbStoreOptions
get => GetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl);
set => SetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl, value);
}
internal CultureInfo PreviousCulture { get; set; } = default!;
}

View File

@@ -3,17 +3,11 @@
using Snap.Hutao.Model;
using Snap.Hutao.Web.Hoyolab;
using System.Globalization;
namespace Snap.Hutao.Service;
internal static class AppOptionsExtension
{
public static NameValue<CultureInfo>? GetCurrentCultureForSelectionOrDefault(this AppOptions appOptions)
{
return appOptions.Cultures.SingleOrDefault(c => c.Value == appOptions.CurrentCulture);
}
public static NameValue<Region>? GetCurrentRegionForSelectionOrDefault(this AppOptions appOptions)
{
return appOptions.LazyRegions.Value.SingleOrDefault(c => c.Value.Value == appOptions.Region.Value);

View File

@@ -0,0 +1,43 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction;
using System.Globalization;
namespace Snap.Hutao.Service;
[ConstructorGenerated(CallBaseConstructor = true)]
[Injection(InjectAs.Singleton)]
internal sealed partial class CultureOptions : DbStoreOptions
{
private CultureInfo? currentCulture;
private string? localeName;
private string? languageCode;
public List<NameValue<CultureInfo>> Cultures { get; } = SupportedCultures.Get();
public CultureInfo CurrentCulture
{
get => GetOption(ref currentCulture, SettingEntry.Culture, CultureInfo.GetCultureInfo, CultureInfo.CurrentCulture);
set => SetOption(ref currentCulture, SettingEntry.Culture, value, value => value.Name);
}
public CultureInfo SystemCulture { get; set; } = default!;
public string LocaleName { get => localeName ??= CultureOptionsExtension.GetLocaleName(CurrentCulture); }
public string LanguageCode
{
get
{
if (languageCode is null && !LocaleNames.TryGetLanguageCodeFromLocaleName(LocaleName, out languageCode))
{
throw new KeyNotFoundException($"Invalid localeName: '{LocaleName}'");
}
return languageCode;
}
}
}

View File

@@ -1,24 +1,19 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model;
using System.Globalization;
using System.IO;
namespace Snap.Hutao.Service.Metadata;
namespace Snap.Hutao.Service;
internal static class MetadataOptionsExtension
internal static class CultureOptionsExtension
{
public static string GetLocalizedLocalFile(this MetadataOptions options, string fileNameWithExtension)
public static NameValue<CultureInfo>? GetCurrentCultureForSelectionOrDefault(this CultureOptions options)
{
return Path.Combine(options.LocalizedDataFolder, fileNameWithExtension);
return options.Cultures.SingleOrDefault(c => c.Value == options.CurrentCulture);
}
public static string GetLocalizedRemoteFile(this MetadataOptions options, string fileNameWithExtension)
{
return Web.HutaoEndpoints.Metadata(options.LocaleName, fileNameWithExtension);
}
public static bool LanguageCodeFitsCurrentLocale(this MetadataOptions options, string? languageCode)
public static bool LanguageCodeFitsCurrentLocale(this CultureOptions options, string? languageCode)
{
if (string.IsNullOrEmpty(languageCode))
{

View File

@@ -18,7 +18,7 @@ namespace Snap.Hutao.Service.GachaLog.QueryProvider;
internal sealed partial class GachaLogQueryManualInputProvider : IGachaLogQueryProvider
{
private readonly IContentDialogFactory contentDialogFactory;
private readonly MetadataOptions metadataOptions;
private readonly CultureOptions cultureOptions;
/// <inheritdoc/>
public async ValueTask<ValueResult<bool, GachaLogQuery>> GetQueryAsync()
@@ -33,13 +33,13 @@ internal sealed partial class GachaLogQueryManualInputProvider : IGachaLogQueryP
if (query.TryGetSingleValue("auth_appid", out string? appId) && appId is "webview_gacha")
{
string? queryLanguageCode = query["lang"];
if (metadataOptions.LanguageCodeFitsCurrentLocale(queryLanguageCode))
if (cultureOptions.LanguageCodeFitsCurrentLocale(queryLanguageCode))
{
return new(true, new(queryString));
}
else
{
string message = SH.FormatServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale(queryLanguageCode, metadataOptions.LanguageCode);
string message = SH.FormatServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale(queryLanguageCode, cultureOptions.LanguageCode);
return new(false, message);
}
}

View File

@@ -20,7 +20,7 @@ namespace Snap.Hutao.Service.GachaLog.QueryProvider;
internal sealed partial class GachaLogQuerySTokenProvider : IGachaLogQueryProvider
{
private readonly BindingClient2 bindingClient2;
private readonly MetadataOptions metadataOptions;
private readonly CultureOptions cultureOptions;
private readonly IUserService userService;
/// <inheritdoc/>
@@ -38,7 +38,7 @@ internal sealed partial class GachaLogQuerySTokenProvider : IGachaLogQueryProvid
if (authkeyResponse.IsOk())
{
return new(true, new(ComposeQueryString(data, authkeyResponse.Data, metadataOptions.LanguageCode)));
return new(true, new(ComposeQueryString(data, authkeyResponse.Data, cultureOptions.LanguageCode)));
}
else
{

View File

@@ -22,7 +22,7 @@ namespace Snap.Hutao.Service.GachaLog.QueryProvider;
internal sealed partial class GachaLogQueryWebCacheProvider : IGachaLogQueryProvider
{
private readonly IGameServiceFacade gameService;
private readonly MetadataOptions metadataOptions;
private readonly CultureOptions cultureOptions;
/// <summary>
/// 获取缓存文件路径
@@ -90,12 +90,12 @@ internal sealed partial class GachaLogQueryWebCacheProvider : IGachaLogQueryProv
NameValueCollection query = HttpUtility.ParseQueryString(result.TrimEnd("#/log"));
string? queryLanguageCode = query["lang"];
if (metadataOptions.LanguageCodeFitsCurrentLocale(queryLanguageCode))
if (cultureOptions.LanguageCodeFitsCurrentLocale(queryLanguageCode))
{
return new(true, new(result));
}
string message = SH.FormatServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale(queryLanguageCode, metadataOptions.LanguageCode);
string message = SH.FormatServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale(queryLanguageCode, cultureOptions.LanguageCode);
return new(false, message);
}
}

View File

@@ -17,7 +17,7 @@ internal sealed partial class UIGFExportService : IUIGFExportService
{
private readonly IGachaLogDbService gachaLogDbService;
private readonly RuntimeOptions runtimeOptions;
private readonly MetadataOptions metadataOptions;
private readonly CultureOptions cultureOptions;
private readonly ITaskContext taskContext;
/// <inheritdoc/>
@@ -31,7 +31,7 @@ internal sealed partial class UIGFExportService : IUIGFExportService
UIGF uigf = new()
{
Info = UIGFInfo.From(runtimeOptions, metadataOptions, archive.Uid),
Info = UIGFInfo.From(runtimeOptions, cultureOptions, archive.Uid),
List = list,
};

View File

@@ -18,7 +18,7 @@ namespace Snap.Hutao.Service.GachaLog;
internal sealed partial class UIGFImportService : IUIGFImportService
{
private readonly ILogger<UIGFImportService> logger;
private readonly MetadataOptions metadataOptions;
private readonly CultureOptions cultureOptions;
private readonly IGachaLogDbService gachaLogDbService;
private readonly ITaskContext taskContext;
@@ -37,9 +37,9 @@ internal sealed partial class UIGFImportService : IUIGFImportService
// v2.1 only support CHS
if (version is UIGFVersion.Major2Minor2OrLower)
{
if (!metadataOptions.LanguageCodeFitsCurrentLocale(uigf.Info.Language))
if (!cultureOptions.LanguageCodeFitsCurrentLocale(uigf.Info.Language))
{
string message = SH.FormatServiceGachaUIGFImportLanguageNotMatch(uigf.Info.Language, metadataOptions.LanguageCode);
string message = SH.FormatServiceGachaUIGFImportLanguageNotMatch(uigf.Info.Language, cultureOptions.LanguageCode);
ThrowHelper.InvalidOperation(message);
}

View File

@@ -7,11 +7,9 @@ using Snap.Hutao.Factory.ContentDialog;
using Snap.Hutao.Factory.Progress;
using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Service.Game.Package;
using Snap.Hutao.Service.Game.PathAbstraction;
using Snap.Hutao.View.Dialog;
using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher;
using Snap.Hutao.Web.Response;
using System.Collections.Immutable;
using System.IO;
namespace Snap.Hutao.Service.Game.Launching.Handler;

View File

@@ -1,7 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Service.Metadata;
namespace Snap.Hutao.Service;
/// <summary>
/// 本地化名称

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Snap.Hutao.Core;
using System.Globalization;
using System.IO;
namespace Snap.Hutao.Service.Metadata;
@@ -10,10 +11,9 @@ namespace Snap.Hutao.Service.Metadata;
[Injection(InjectAs.Singleton)]
internal sealed partial class MetadataOptions
{
private readonly AppOptions appOptions;
private readonly RuntimeOptions hutaoOptions;
private readonly CultureOptions cultureOptions;
private readonly RuntimeOptions runtimeOptions;
private string? localeName;
private string? fallbackDataFolder;
private string? localizedDataFolder;
@@ -23,7 +23,7 @@ internal sealed partial class MetadataOptions
{
if (fallbackDataFolder is null)
{
fallbackDataFolder = Path.Combine(hutaoOptions.DataFolder, "Metadata", "CHS");
fallbackDataFolder = Path.Combine(runtimeOptions.DataFolder, "Metadata", "CHS");
Directory.CreateDirectory(fallbackDataFolder);
}
@@ -37,7 +37,7 @@ internal sealed partial class MetadataOptions
{
if (localizedDataFolder is null)
{
localizedDataFolder = Path.Combine(hutaoOptions.DataFolder, "Metadata", LocaleName);
localizedDataFolder = Path.Combine(runtimeOptions.DataFolder, "Metadata", cultureOptions.LocaleName);
Directory.CreateDirectory(localizedDataFolder);
}
@@ -45,21 +45,13 @@ internal sealed partial class MetadataOptions
}
}
public string LocaleName
public string GetLocalizedLocalFile(string fileNameWithExtension)
{
get => localeName ??= MetadataOptionsExtension.GetLocaleName(appOptions.CurrentCulture);
return Path.Combine(LocalizedDataFolder, fileNameWithExtension);
}
public string LanguageCode
public string GetLocalizedRemoteFile(string fileNameWithExtension)
{
get
{
if (LocaleNames.TryGetLanguageCodeFromLocaleName(LocaleName, out string? languageCode))
{
return languageCode;
}
throw new KeyNotFoundException($"Invalid localeName: '{LocaleName}'");
}
return Web.HutaoEndpoints.Metadata(cultureOptions.LocaleName, fileNameWithExtension);
}
}

View File

@@ -55,7 +55,7 @@
<GridView
Grid.Row="0"
ItemTemplate="{StaticResource LanguageTemplate}"
ItemsSource="{Binding AppOptions.Cultures}"
ItemsSource="{Binding CultureOptions.Cultures}"
SelectedItem="{Binding SelectedCulture, Mode=TwoWay}"
SelectionMode="Single"/>
</Grid>

View File

@@ -97,7 +97,7 @@
Description="{shcm:ResourceString Name=ViewPageSettingElevatedModeDescription}"
Header="{shcm:ResourceString Name=ViewPageSettingElevatedModeRestartAction}"
IsClickEnabled="True"
IsEnabled="{Binding HutaoOptions.IsElevated, Converter={StaticResource BoolNegationConverter}}"/>
IsEnabled="{Binding RuntimeOptions.IsElevated, Converter={StaticResource BoolNegationConverter}}"/>
<cwc:SettingsCard
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingCreateDesktopShortcutAction}"
Command="{Binding CreateDesktopShortcutCommand}"
@@ -112,7 +112,7 @@
<Grid Padding="16" HorizontalAlignment="Left">
<StackPanel Grid.Column="0" Spacing="{StaticResource SettingsCardSpacing}">
<cwc:SettingsExpander
Description="{Binding HutaoOptions.Version}"
Description="{Binding RuntimeOptions.Version}"
Header="{shcm:ResourceString Name=AppName}"
HeaderIcon="{shcm:FontIcon Glyph=&#xECAA;}"
IsExpanded="True">
@@ -121,11 +121,11 @@
ActionIcon="{shcm:FontIcon Glyph=&#xE8C8;}"
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingCopyDeviceIdAction}"
Command="{Binding CopyDeviceIdCommand}"
Description="{Binding HutaoOptions.DeviceId}"
Description="{Binding RuntimeOptions.DeviceId}"
Header="{shcm:ResourceString Name=ViewPageSettingDeviceIdHeader}"
IsClickEnabled="True"/>
<cwc:SettingsCard Description="{Binding IPInformation}" Header="{shcm:ResourceString Name=ViewPageSettingDeviceIpHeader}"/>
<cwc:SettingsCard Description="{Binding HutaoOptions.WebView2Version}" Header="{shcm:ResourceString Name=ViewPageSettingWebview2Header}"/>
<cwc:SettingsCard Description="{Binding RuntimeOptions.WebView2Version}" Header="{shcm:ResourceString Name=ViewPageSettingWebview2Header}"/>
</cwc:SettingsExpander.Items>
</cwc:SettingsExpander>
<!--
@@ -213,7 +213,7 @@
<shc:SizeRestrictedContentControl>
<ComboBox
DisplayMemberPath="Name"
ItemsSource="{Binding AppOptions.Cultures}"
ItemsSource="{Binding CultureOptions.Cultures}"
SelectedItem="{Binding SelectedCulture, Mode=TwoWay}"/>
</shc:SizeRestrictedContentControl>
</cwc:SettingsCard>
@@ -416,7 +416,7 @@
<cwc:SettingsCard
Header="{shcm:ResourceString Name=ViewPageSettingIsAdvancedLaunchOptionsEnabledHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE730;}"
IsEnabled="{Binding HutaoOptions.IsElevated}">
IsEnabled="{Binding RuntimeOptions.IsElevated}">
<cwc:SettingsCard.Description>
<StackPanel>
<TextBlock
@@ -427,7 +427,7 @@
</StackPanel>
</cwc:SettingsCard.Description>
<StackPanel Orientation="Horizontal">
<shvc:Elevation Visibility="{Binding HutaoOptions.IsElevated, Converter={StaticResource BoolToVisibilityRevertConverter}}"/>
<shvc:Elevation Visibility="{Binding RuntimeOptions.IsElevated, Converter={StaticResource BoolToVisibilityRevertConverter}}"/>
<ToggleSwitch Width="120" IsOn="{Binding IsAdvancedLaunchOptionsEnabled, Mode=TwoWay}"/>
</StackPanel>
</cwc:SettingsCard>

View File

@@ -37,8 +37,8 @@ internal sealed class DownloadSummary : ObservableObject
taskContext = serviceProvider.GetRequiredService<ITaskContext>();
httpClient = serviceProvider.GetRequiredService<HttpClient>();
imageCache = serviceProvider.GetRequiredService<IImageCache>();
RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(hutaoOptions.UserAgent);
RuntimeOptions runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(runtimeOptions.UserAgent);
this.serviceProvider = serviceProvider;

View File

@@ -20,7 +20,7 @@ internal sealed partial class GuideViewModel : Abstraction.ViewModel
{
private readonly IServiceProvider serviceProvider;
private readonly ITaskContext taskContext;
private readonly AppOptions appOptions;
private readonly CultureOptions cultureOptions;
private readonly RuntimeOptions runtimeOptions;
private string nextOrCompleteButtonText = SH.ViewModelGuideActionNext;
@@ -75,18 +75,18 @@ internal sealed partial class GuideViewModel : Abstraction.ViewModel
public bool IsNextOrCompleteButtonEnabled { get => isNextOrCompleteButtonEnabled; set => SetProperty(ref isNextOrCompleteButtonEnabled, value); }
public AppOptions AppOptions { get => appOptions; }
public CultureOptions CultureOptions { get => cultureOptions; }
public RuntimeOptions RuntimeOptions { get => runtimeOptions; }
public NameValue<CultureInfo>? SelectedCulture
{
get => selectedCulture ??= AppOptions.GetCurrentCultureForSelectionOrDefault();
get => selectedCulture ??= CultureOptions.GetCurrentCultureForSelectionOrDefault();
set
{
if (SetProperty(ref selectedCulture, value) && value is not null)
{
AppOptions.CurrentCulture = value.Value;
CultureOptions.CurrentCulture = value.Value;
++State;
AppInstance.Restart(string.Empty);
}

View File

@@ -24,8 +24,8 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
private readonly IHutaoAsAService hutaoAsAService;
private readonly IAnnouncementService announcementService;
private readonly HutaoUserOptions hutaoUserOptions;
private readonly CultureOptions cultureOptions;
private readonly ITaskContext taskContext;
private readonly MetadataOptions metadataOptions;
private readonly AppOptions appOptions;
private AnnouncementWrapper? announcement;
@@ -65,7 +65,7 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
{
try
{
AnnouncementWrapper announcementWrapper = await announcementService.GetAnnouncementWrapperAsync(metadataOptions.LanguageCode, appOptions.Region, CancellationToken).ConfigureAwait(false);
AnnouncementWrapper announcementWrapper = await announcementService.GetAnnouncementWrapperAsync(cultureOptions.LanguageCode, appOptions.Region, CancellationToken).ConfigureAwait(false);
await taskContext.SwitchToMainThreadAsync();
Announcement = announcementWrapper;
}

View File

@@ -51,6 +51,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
private readonly IShellLinkInterop shellLinkInterop;
private readonly HutaoUserOptions hutaoUserOptions;
private readonly IInfoBarService infoBarService;
private readonly CultureOptions cultureOptions;
private readonly RuntimeOptions runtimeOptions;
private readonly LaunchOptions launchOptions;
private readonly HotKeyOptions hotKeyOptions;
@@ -67,7 +68,9 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
public AppOptions AppOptions { get => appOptions; }
public RuntimeOptions HutaoOptions { get => runtimeOptions; }
public CultureOptions CultureOptions { get => cultureOptions; }
public RuntimeOptions RuntimeOptions { get => runtimeOptions; }
public HutaoUserOptions UserOptions { get => hutaoUserOptions; }
@@ -93,12 +96,12 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
public NameValue<CultureInfo>? SelectedCulture
{
get => selectedCulture ??= AppOptions.GetCurrentCultureForSelectionOrDefault();
get => selectedCulture ??= CultureOptions.GetCurrentCultureForSelectionOrDefault();
set
{
if (SetProperty(ref selectedCulture, value) && value is not null)
{
AppOptions.CurrentCulture = value.Value;
CultureOptions.CurrentCulture = value.Value;
AppInstance.Restart(string.Empty);
}
}
@@ -298,7 +301,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
{
try
{
clipboardInterop.SetText(HutaoOptions.DeviceId);
clipboardInterop.SetText(RuntimeOptions.DeviceId);
infoBarService.Success(SH.ViewModelSettingCopyDeviceIdSuccess);
}
catch (COMException ex)

View File

@@ -4,6 +4,7 @@
using Microsoft.Web.WebView2.Core;
using Snap.Hutao.Core.DependencyInjection.Abstraction;
using Snap.Hutao.Core.IO.DataTransfer;
using Snap.Hutao.Service;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Service.Notification;
using Snap.Hutao.Service.User;
@@ -183,13 +184,13 @@ internal class MiHoYoJSBridge
protected virtual JsResult<Dictionary<string, string>> GetCurrentLocale(JsParam<PushPagePayload> param)
{
MetadataOptions metadataOptions = serviceProvider.GetRequiredService<MetadataOptions>();
CultureOptions cultureOptions = serviceProvider.GetRequiredService<CultureOptions>();
return new()
{
Data = new()
{
["language"] = metadataOptions.LanguageCode,
["language"] = cultureOptions.LanguageCode,
["timeZone"] = "GMT+8",
},
};

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Service;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.ViewModel.User;
using Snap.Hutao.Web.Hoyolab.DataSigning;
@@ -23,14 +24,14 @@ internal sealed partial class SignInClient : ISignInClient
{
private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory;
private readonly HomaGeetestClient homaGeetestClient;
private readonly MetadataOptions metadataOptions;
private readonly CultureOptions cultureOptions;
private readonly ILogger<SignInClient> logger;
private readonly HttpClient httpClient;
public async ValueTask<Response<ExtraAwardInfo>> GetExtraAwardInfoAsync(UserAndUid userAndUid, CancellationToken token = default)
{
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(ApiEndpoints.LunaExtraAward(userAndUid.Uid, metadataOptions.LanguageCode))
.SetRequestUri(ApiEndpoints.LunaExtraAward(userAndUid.Uid, cultureOptions.LanguageCode))
.SetUserCookieAndFpHeader(userAndUid, CookieType.CookieToken)
.SetHeader("x-rpc-signgame", "hk4e")
.Get();
@@ -47,7 +48,7 @@ internal sealed partial class SignInClient : ISignInClient
public async ValueTask<Response<SignInRewardInfo>> GetInfoAsync(UserAndUid userAndUid, CancellationToken token = default)
{
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(ApiEndpoints.LunaInfo(userAndUid.Uid, metadataOptions.LanguageCode))
.SetRequestUri(ApiEndpoints.LunaInfo(userAndUid.Uid, cultureOptions.LanguageCode))
.SetUserCookieAndFpHeader(userAndUid, CookieType.CookieToken)
.SetHeader("x-rpc-signgame", "hk4e")
.Get();
@@ -81,7 +82,7 @@ internal sealed partial class SignInClient : ISignInClient
public async ValueTask<Response<Reward>> GetRewardAsync(Model.Entity.User user, CancellationToken token = default)
{
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(ApiEndpoints.LunaHome(metadataOptions.LanguageCode))
.SetRequestUri(ApiEndpoints.LunaHome(cultureOptions.LanguageCode))
.SetUserCookieAndFpHeader(user, CookieType.CookieToken)
.SetHeader("x-rpc-signgame", "hk4e")
.Get();

View File

@@ -0,0 +1,34 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Web.Hutao.Response;
using Snap.Hutao.Web.Request.Builder;
using Snap.Hutao.Web.Request.Builder.Abstraction;
using System.Net.Http;
namespace Snap.Hutao.Web.Hutao.Algolia;
internal sealed class AlgoliaHierarchy
{
[JsonPropertyName("lvl0")]
public string? Lvl0 { get; set; }
[JsonPropertyName("lvl1")]
public string? Lvl1 { get; set; }
[JsonPropertyName("lvl2")]
public string? Lvl2 { get; set; }
[JsonPropertyName("lvl3")]
public string? Lvl3 { get; set; }
[JsonPropertyName("lvl4")]
public string? Lvl4 { get; set; }
[JsonPropertyName("lvl5")]
public string? Lvl5 { get; set; }
[JsonPropertyName("lvl6")]
public string? Lvl6 { get; set; }
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Web.Hutao.Response;
using Snap.Hutao.Web.Request.Builder;
using Snap.Hutao.Web.Request.Builder.Abstraction;
using System.Net.Http;
namespace Snap.Hutao.Web.Hutao.Algolia;
internal sealed class AlgoliaHit
{
[JsonPropertyName("url")]
public string Url { get; set; } = default!;
[JsonPropertyName("hierarchy")]
public AlgoliaHierarchy Hierarchy { get; set; } = default!;
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Web.Hutao.Response;
using Snap.Hutao.Web.Request.Builder;
using Snap.Hutao.Web.Request.Builder.Abstraction;
using System.Net.Http;
namespace Snap.Hutao.Web.Hutao.Algolia;
internal sealed class AlgoliaRequest
{
[JsonPropertyName("query")]
public string Query { get; set; } = default!;
[JsonPropertyName("indexName")]
public string IndexName { get; set; } = default!;
[JsonPropertyName("params")]
public string Params { get; set; } = default!;
}

View File

@@ -0,0 +1,10 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hutao.Algolia;
internal sealed class AlgoliaRequestsWrapper
{
[JsonPropertyName("requests")]
public List<AlgoliaRequest> Requests { get; set; } = default!;
}

View File

@@ -0,0 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hutao.Algolia;
internal sealed class AlgoliaResponse
{
public List<AlgoliaResult> Results { get; set; } = default!;
}

View File

@@ -0,0 +1,16 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Web.Hutao.Response;
using Snap.Hutao.Web.Request.Builder;
using Snap.Hutao.Web.Request.Builder.Abstraction;
using System.Net.Http;
namespace Snap.Hutao.Web.Hutao.Algolia;
internal sealed class AlgoliaResult
{
[JsonPropertyName("hits")]
public List<AlgoliaHit> Hits { get; set; } = default!;
}

View File

@@ -0,0 +1,46 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Web.Request.Builder;
using Snap.Hutao.Web.Request.Builder.Abstraction;
using System.Net.Http;
namespace Snap.Hutao.Web.Hutao.Algolia;
[HttpClient(HttpClientConfiguration.Default)]
[ConstructorGenerated(ResolveHttpClient = true)]
internal sealed partial class HutaoDocumentationClient
{
private const string AlgoliaApiKey = "72d7a9a0f9f0466218ea19988886dce8";
private const string AlgoliaApplicationId = "28CTGDOOQD";
private const string AlgolianetIndexesQueries = $"https://28ctgdooqd-1.algolianet.com/1/indexes/*/queries";
private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory;
private readonly ILogger<HutaoDocumentationClient> logger;
private readonly HttpClient httpClient;
public async ValueTask<AlgoliaResponse?> QueryAsync(string query, string language, CancellationToken token)
{
AlgoliaRequestsWrapper data = new()
{
Requests =
[
new AlgoliaRequest
{
Query = query,
IndexName = "hutao",
Params = $"""facetFilters=["lang:{language}"]""",
},
],
};
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(AlgolianetIndexesQueries)
.SetHeader("x-algolia-api-key", AlgoliaApiKey)
.SetHeader("x-algolia-application-id", AlgoliaApplicationId)
.PostJson(data);
return await builder.TryCatchSendAsync<AlgoliaResponse>(httpClient, logger, token).ConfigureAwait(false);
}
}

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Service;
using Snap.Hutao.Service.Hutao;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Web.Hutao.Response;
@@ -21,13 +22,13 @@ internal sealed partial class HutaoAsAServiceClient
private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory;
private readonly ILogger<HutaoAsAServiceClient> logger;
private readonly HutaoUserOptions hutaoUserOptions;
private readonly MetadataOptions metadataOptions;
private readonly CultureOptions cultureOptions;
private readonly HttpClient httpClient;
public async ValueTask<HutaoResponse<List<Announcement>>> GetAnnouncementListAsync(List<long> excluedeIds, CancellationToken token = default)
{
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(HutaoEndpoints.Announcement(metadataOptions.LocaleName))
.SetRequestUri(HutaoEndpoints.Announcement(cultureOptions.LocaleName))
.PostJson(excluedeIds);
HutaoResponse<List<Announcement>>? resp = await builder