From ba6ee9bb857df35f2306f6b4aab1deb73d5720ed Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Thu, 16 Nov 2023 13:15:37 +0800 Subject: [PATCH] replace format extension --- .../Resx/ResxGenerator.cs | 80 +++++++++++++------ .../Control/Image/CompositionImage.cs | 2 +- .../DatabaseCorruptedException.cs | 2 +- .../UserdataCorruptedException.cs | 2 +- .../Snap.Hutao/Core/IO/PickerExtension.cs | 2 +- .../Core/Windowing/WindowController.cs | 2 +- .../Snap.Hutao/Extension/StringExtension.cs | 18 ----- .../Snap.Hutao/Model/Entity/DailyNoteEntry.cs | 4 +- .../Model/Entity/ObjectCacheEntry.cs | 2 +- .../Model/InterChange/Achievement/UIAFInfo.cs | 2 +- .../Model/InterChange/GachaLog/UIGFInfo.cs | 2 +- .../Model/InterChange/Inventory/UIIFInfo.cs | 2 +- .../Model/Metadata/Avatar/FetterInfo.cs | 2 +- .../Model/Metadata/Weapon/LevelDescription.cs | 2 +- .../Service/Achievement/ImportResult.cs | 2 +- .../AvatarInfo/AvatarInfoDbBulkOperation.cs | 12 +-- .../Factory/SummaryAvatarFactory.cs | 6 +- .../DailyNoteNotificationOperation.cs | 4 +- .../Factory/GachaStatisticsFactory.cs | 2 +- .../Factory/HutaoStatisticsFactory.cs | 4 +- .../Service/GachaLog/GachaLogDbService.cs | 2 +- .../Service/GachaLog/GachaLogFetchStatus.cs | 2 +- .../GachaLogQueryManualInputProvider.cs | 3 +- .../GachaLogQueryWebCacheProvider.cs | 7 +- .../Service/GachaLog/UIGFImportService.cs | 8 +- .../GameChannelOptionsService.cs | 4 +- .../Game/GameFileOperationException.cs | 2 +- .../Service/Game/Package/PackageConverter.cs | 15 ++-- .../Service/Hutao/HutaoAsAService.cs | 4 +- .../Snap.Hutao/Service/Hutao/HutaoCache.cs | 4 +- .../Service/Hutao/HutaoUserOptions.cs | 6 +- .../Service/Hutao/ObjectCacheDbService.cs | 2 +- .../Service/SignIn/SignInService.cs | 4 +- .../Service/User/UserFingerprintService.cs | 2 +- src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 4 + .../Snap.Hutao/View/TitleView.xaml.cs | 22 ++--- .../ViewModel/Achievement/AchievementView.cs | 4 +- .../Achievement/AchievementViewModel.cs | 6 +- .../AvatarProperty/AvatarPropertyViewModel.cs | 4 +- .../ViewModel/AvatarProperty/WeaponView.cs | 2 +- .../Snap.Hutao/ViewModel/Complex/Team.cs | 2 +- .../ViewModel/Complex/TeamAppearanceView.cs | 2 +- .../ViewModel/GachaLog/GachaLogViewModel.cs | 2 +- .../ViewModel/GachaLog/TypedWishSummary.cs | 12 +-- .../Snap.Hutao/ViewModel/GachaLog/Wish.cs | 2 +- .../ViewModel/Game/LaunchGameViewModel.cs | 2 +- .../ViewModel/Home/AnnouncementViewModel.cs | 2 +- .../ViewModel/Setting/SettingViewModel.cs | 3 +- .../ViewModel/SpiralAbyss/FloorView.cs | 2 +- .../ViewModel/SpiralAbyss/LevelView.cs | 2 +- .../ViewModel/SpiralAbyss/SpiralAbyssView.cs | 2 +- .../ViewModel/User/UserViewModel.cs | 8 +- .../Snap.Hutao/Web/Enka/EnkaClient.cs | 5 +- .../Hk4e/Common/Announcement/Announcement.cs | 12 ++- .../Takumi/GameRecord/DailyNote/DailyNote.cs | 8 +- .../Takumi/GameRecord/DailyNote/Expedition.cs | 4 +- .../GameRecord/DailyNote/RecoveryTime.cs | 16 ++-- .../Web/Hutao/Geetest/HomaGeetestClient.cs | 3 +- .../Snap.Hutao/Web/Hutao/HutaoResponse.cs | 10 +-- .../Web/Hutao/Log/HomaLogUploadClient.cs | 2 +- .../Snap.Hutao/Web/Response/Response.cs | 14 ++-- 61 files changed, 190 insertions(+), 186 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Resx/ResxGenerator.cs b/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Resx/ResxGenerator.cs index 36e0498c..d9670fca 100644 --- a/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Resx/ResxGenerator.cs +++ b/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Resx/ResxGenerator.cs @@ -44,39 +44,39 @@ public sealed class ResxGenerator : IIncrementalGenerator .OrderBy(x => x.Key, StringComparer.Ordinal); List> resxGroups = [.. group]; - foreach (IGrouping? resxGroug in resxGroups) + foreach (IGrouping? resxGroup in resxGroups) { - string? rootNamespaceConfiguration = GetMetadataValue(context, options, "RootNamespace", resxGroug); - string? projectDirConfiguration = GetMetadataValue(context, options, "ProjectDir", resxGroug); - string? namespaceConfiguration = GetMetadataValue(context, options, "Namespace", "DefaultResourcesNamespace", resxGroug); - string? resourceNameConfiguration = GetMetadataValue(context, options, "ResourceName", globalName: null, resxGroug); - string? classNameConfiguration = GetMetadataValue(context, options, "ClassName", globalName: null, resxGroug); + string? rootNamespaceConfiguration = GetMetadataValue(context, options, "RootNamespace", resxGroup); + string? projectDirConfiguration = GetMetadataValue(context, options, "ProjectDir", resxGroup); + string? namespaceConfiguration = GetMetadataValue(context, options, "Namespace", "DefaultResourcesNamespace", resxGroup); + string? resourceNameConfiguration = GetMetadataValue(context, options, "ResourceName", globalName: null, resxGroup); + string? classNameConfiguration = GetMetadataValue(context, options, "ClassName", globalName: null, resxGroup); string rootNamespace = rootNamespaceConfiguration ?? assemblyName ?? ""; string projectDir = projectDirConfiguration ?? assemblyName ?? ""; - string? defaultResourceName = ComputeResourceName(rootNamespace, projectDir, resxGroug.Key); - string? defaultNamespace = ComputeNamespace(rootNamespace, projectDir, resxGroug.Key); + string? defaultResourceName = ComputeResourceName(rootNamespace, projectDir, resxGroup.Key); + string? defaultNamespace = ComputeNamespace(rootNamespace, projectDir, resxGroup.Key); string? ns = namespaceConfiguration ?? defaultNamespace; string? resourceName = resourceNameConfiguration ?? defaultResourceName; - string className = classNameConfiguration ?? ToCSharpNameIdentifier(Path.GetFileName(resxGroug.Key)); + string className = classNameConfiguration ?? ToCSharpNameIdentifier(Path.GetFileName(resxGroup.Key)); if (ns == null) { - context.ReportDiagnostic(Diagnostic.Create(InvalidPropertiesForNamespace, location: null, resxGroug.First().Path)); + context.ReportDiagnostic(Diagnostic.Create(InvalidPropertiesForNamespace, location: null, resxGroup.First().Path)); } if (resourceName == null) { - context.ReportDiagnostic(Diagnostic.Create(InvalidPropertiesForResourceName, location: null, resxGroug.First().Path)); + context.ReportDiagnostic(Diagnostic.Create(InvalidPropertiesForResourceName, location: null, resxGroup.First().Path)); } - List? entries = LoadResourceFiles(context, resxGroug); + List? entries = LoadResourceFiles(context, resxGroup); string content = $""" // Debug info: - // key: {resxGroug.Key} - // files: {string.Join(", ", resxGroug.Select(f => f.Path))} + // key: {resxGroup.Key} + // files: {string.Join(", ", resxGroup.Select(f => f.Path))} // RootNamespace (metadata): {rootNamespaceConfiguration} // ProjectDir (metadata): {projectDirConfiguration} // Namespace / DefaultResourcesNamespace (metadata): {namespaceConfiguration} @@ -97,7 +97,7 @@ public sealed class ResxGenerator : IIncrementalGenerator content += GenerateCode(ns, className, resourceName, entries, supportNullableReferenceTypes); } - context.AddSource($"{Path.GetFileName(resxGroug.Key)}.resx.g.cs", SourceText.From(content, Encoding.UTF8)); + context.AddSource($"{Path.GetFileName(resxGroup.Key)}.resx.g.cs", SourceText.From(content, Encoding.UTF8)); } } @@ -285,7 +285,10 @@ public sealed class ResxGenerator : IIncrementalGenerator if (!entry.IsFileRef) { - summary.Add(new XElement("para", $"Value: \"{entry.Value}\".")); + foreach((string? each, string locale) in entry.Values.Zip(entry.Locales,(x,y)=>(x,y))) + { + summary.Add(new XElement("para", $"{GetStringWithPadding(locale, 8)} Value: \"{each}\"")); + } } string comment = summary.ToString().Replace("\r\n", "\r\n /// ", StringComparison.Ordinal); @@ -299,9 +302,9 @@ public sealed class ResxGenerator : IIncrementalGenerator """); - if (entry.Value != null) + if (entry.Values.FirstOrDefault() is string value) { - int args = Regex.Matches(entry.Value, "\\{(?[0-9]+)(\\:[^}]*)?\\}", RegexOptions.ExplicitCapture | RegexOptions.CultureInvariant) + int args = Regex.Matches(value, "\\{(?[0-9]+)(\\:[^}]*)?\\}", RegexOptions.ExplicitCapture | RegexOptions.CultureInvariant) .Cast() .Select(m => int.Parse(m.Groups["num"].Value, CultureInfo.InvariantCulture)) .Distinct() @@ -360,6 +363,16 @@ public sealed class ResxGenerator : IIncrementalGenerator return sb.ToString(); } + private static string GetStringWithPadding(string source, int length) + { + if (source.Length >= length) + { + return source; + } + + return source + new string('_', length - source.Length); + } + private static string? ComputeResourceName(string rootNamespace, string projectDir, string resourcePath) { string fullProjectDir = EnsureEndSeparator(Path.GetFullPath(projectDir)); @@ -404,7 +417,7 @@ public sealed class ResxGenerator : IIncrementalGenerator foreach (AdditionalText? entry in resxGroug.OrderBy(file => file.Path, StringComparer.Ordinal)) { SourceText? content = entry.GetText(context.CancellationToken); - if (content == null) + if (content is null) { continue; } @@ -423,10 +436,12 @@ public sealed class ResxGenerator : IIncrementalGenerator if (existingEntry != null) { existingEntry.Comment ??= comment; + existingEntry.Values.Add(value); + existingEntry.Locales.Add(GetLocaleName(entry.Path)); } else { - entries.Add(new ResxEntry { Name = name, Value = value, Comment = comment, Type = type }); + entries.Add(new() { Name = name, Values = [value], Locales = [GetLocaleName(entry.Path)], Comment = comment, Type = type }); } } } @@ -532,15 +547,28 @@ public sealed class ResxGenerator : IIncrementalGenerator return pathWithoutExtension; } - return Regex.IsMatch(pathWithoutExtension.Substring(indexOf + 1), "^[a-zA-Z]{2}(-[a-zA-Z]{2})?$", RegexOptions.ExplicitCapture | RegexOptions.CultureInvariant, TimeSpan.FromSeconds(1)) + return Regex.IsMatch(pathWithoutExtension.Substring(indexOf + 1), "^[a-zA-Z]{2}(-[a-zA-Z]{2,4})?$", RegexOptions.ExplicitCapture | RegexOptions.CultureInvariant, TimeSpan.FromSeconds(1)) ? pathWithoutExtension.Substring(0, indexOf) : pathWithoutExtension; } + private static string GetLocaleName(string path) + { + string fileName = Path.GetFileNameWithoutExtension(path); + int indexOf = fileName.LastIndexOf('.'); + if (indexOf < 0) + { + return "Neutral"; + } + + return fileName.Substring(indexOf + 1); + } + private sealed class ResxEntry { public string? Name { get; set; } - public string? Value { get; set; } + public List Values { get; set; } = default!; + public List Locales { get; set; } = default!; public string? Comment { get; set; } public string? Type { get; set; } @@ -553,9 +581,9 @@ public sealed class ResxGenerator : IIncrementalGenerator return true; } - if (Value != null) + if (Values.FirstOrDefault() is string value) { - string[] parts = Value.Split(';'); + string[] parts = value.Split(';'); if (parts.Length > 1) { string type = parts[1]; @@ -579,9 +607,9 @@ public sealed class ResxGenerator : IIncrementalGenerator return "string"; } - if (Value != null) + if (Values.FirstOrDefault() is string value) { - string[] parts = Value.Split(';'); + string[] parts = value.Split(';'); if (parts.Length > 1) { string type = parts[1]; diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs b/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs index 204ab70d..9cbc5d20 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs @@ -110,7 +110,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co if (exception is HttpRequestException httpRequestException) { - infoBarService.Error(httpRequestException, SH.ControlImageCompositionImageHttpRequest.Format(uri)); + infoBarService.Error(httpRequestException, SH.FormatControlImageCompositionImageHttpRequest(uri)); } else { diff --git a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/DatabaseCorruptedException.cs b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/DatabaseCorruptedException.cs index 1c31ff82..c015352d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/DatabaseCorruptedException.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/DatabaseCorruptedException.cs @@ -15,7 +15,7 @@ internal sealed class DatabaseCorruptedException : Exception /// 消息 /// 内部错误 public DatabaseCorruptedException(string message, Exception? innerException) - : base(SH.CoreExceptionServiceDatabaseCorruptedMessage.Format($"{message}\n{innerException?.Message}"), innerException) + : base(SH.FormatCoreExceptionServiceDatabaseCorruptedMessage($"{message}\n{innerException?.Message}"), innerException) { } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/UserdataCorruptedException.cs b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/UserdataCorruptedException.cs index ee6880d8..934753e1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/UserdataCorruptedException.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/UserdataCorruptedException.cs @@ -15,7 +15,7 @@ internal sealed class UserdataCorruptedException : Exception /// 消息 /// 内部错误 public UserdataCorruptedException(string message, Exception? innerException) - : base(SH.CoreExceptionServiceUserdataCorruptedMessage.Format($"{message}\n{innerException?.Message}"), innerException) + : base(SH.FormatCoreExceptionServiceUserdataCorruptedMessage($"{message}\n{innerException?.Message}"), innerException) { } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs index 76cf669e..1dda04d6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs @@ -98,7 +98,7 @@ internal static class PickerExtension .GetRequiredService() .Warning( SH.CoreIOPickerExtensionPickerExceptionInfoBarTitle, - SH.CoreIOPickerExtensionPickerExceptionInfoBarMessage.Format(exception.Message)); + SH.FormatCoreIOPickerExtensionPickerExceptionInfoBarMessage(exception.Message)); } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs index aa7e8a6b..40bfc52b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs @@ -55,7 +55,7 @@ internal sealed class WindowController { RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); - window.AppWindow.Title = SH.AppNameAndVersion.Format(hutaoOptions.Version); + window.AppWindow.Title = SH.FormatAppNameAndVersion(hutaoOptions.Version); window.AppWindow.SetIcon(Path.Combine(hutaoOptions.InstalledLocation, "Assets/Logo.ico")); ExtendsContentIntoTitleBar(); diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/StringExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/StringExtension.cs index 43f61ed4..8b20c5f4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Extension/StringExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Extension/StringExtension.cs @@ -28,22 +28,4 @@ internal static class StringExtension { return source.AsSpan().TrimEnd(value).ToString(); } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string Format(this string value, object? arg) - { - return string.Format(CultureInfo.CurrentCulture, value, arg); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string Format(this string value, object? arg0, object? arg1) - { - return string.Format(CultureInfo.CurrentCulture, value, arg0, arg1); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string Format(this string value, object? arg0, object? arg1, object? arg2) - { - return string.Format(CultureInfo.CurrentCulture, value, arg0, arg1, arg2); - } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/DailyNoteEntry.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/DailyNoteEntry.cs index 62e69ed8..c1cc069f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/DailyNoteEntry.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/DailyNoteEntry.cs @@ -64,7 +64,7 @@ internal sealed class DailyNoteEntry : ObservableObject, IMappingFrom [NotMapped] - public bool IsExpired { get => ExpireTime < DateTimeOffset.Now; } + public bool IsExpired { get => ExpireTime < DateTimeOffset.UtcNow; } /// /// 值字符串 diff --git a/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Achievement/UIAFInfo.cs b/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Achievement/UIAFInfo.cs index 7df5c9fc..e15c6147 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Achievement/UIAFInfo.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Achievement/UIAFInfo.cs @@ -49,7 +49,7 @@ internal sealed class UIAFInfo : IMappingFrom { return new() { - ExportTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds(), + ExportTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(), ExportApp = SH.AppName, ExportAppVersion = runtimeOptions.Version.ToString(), UIAFVersion = UIAF.CurrentVersion, diff --git a/src/Snap.Hutao/Snap.Hutao/Model/InterChange/GachaLog/UIGFInfo.cs b/src/Snap.Hutao/Snap.Hutao/Model/InterChange/GachaLog/UIGFInfo.cs index f6a0a9cc..0fbbe77f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/InterChange/GachaLog/UIGFInfo.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/InterChange/GachaLog/UIGFInfo.cs @@ -71,7 +71,7 @@ internal sealed class UIGFInfo : IMappingFrom public string BirthFormatted { - get => SH.ModelMetadataFetterInfoBirthdayFormat.Format(BirthMonth, BirthDay); + get => SH.FormatModelMetadataFetterInfoBirthdayFormat(BirthMonth, BirthDay); } /// diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/LevelDescription.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/LevelDescription.cs index f38a6727..a2ff06cf 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/LevelDescription.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/LevelDescription.cs @@ -19,7 +19,7 @@ internal sealed class LevelDescription /// 格式化的等级 /// [JsonIgnore] - public string LevelFormatted { get => SH.ModelWeaponAffixFormat.Format(Level + 1); } + public string LevelFormatted { get => SH.FormatModelWeaponAffixFormat(Level + 1); } /// /// 描述 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/ImportResult.cs b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/ImportResult.cs index cd114b4a..aceaecf4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/ImportResult.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/ImportResult.cs @@ -40,6 +40,6 @@ internal readonly struct ImportResult /// public override string ToString() { - return SH.ServiceAchievementImportResultFormat.Format(Add, Update, Remove); + return SH.FormatServiceAchievementImportResultFormat(Add, Update, Remove); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoDbBulkOperation.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoDbBulkOperation.cs index 7bf6e4ff..50750d87 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoDbBulkOperation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoDbBulkOperation.cs @@ -181,13 +181,13 @@ internal sealed partial class AvatarInfoDbBulkOperation if (entity is null) { entity = EntityAvatarInfo.From(uid, webInfo); - entity.ShowcaseRefreshTime = DateTimeOffset.Now; + entity.ShowcaseRefreshTime = DateTimeOffset.UtcNow; appDbContext.AvatarInfos.AddAndSave(entity); } else { entity.Info = webInfo; - entity.ShowcaseRefreshTime = DateTimeOffset.Now; + entity.ShowcaseRefreshTime = DateTimeOffset.UtcNow; appDbContext.AvatarInfos.UpdateAndSave(entity); } } @@ -200,7 +200,7 @@ internal sealed partial class AvatarInfoDbBulkOperation EnkaAvatarInfo avatarInfo = new() { AvatarId = avatarId }; transformer.Transform(ref avatarInfo, source); entity = EntityAvatarInfo.From(uid, avatarInfo); - entity.CalculatorRefreshTime = DateTimeOffset.Now; + entity.CalculatorRefreshTime = DateTimeOffset.UtcNow; appDbContext.AvatarInfos.AddAndSave(entity); } else @@ -208,7 +208,7 @@ internal sealed partial class AvatarInfoDbBulkOperation EnkaAvatarInfo avatarInfo = entity.Info; transformer.Transform(ref avatarInfo, source); entity.Info = avatarInfo; - entity.CalculatorRefreshTime = DateTimeOffset.Now; + entity.CalculatorRefreshTime = DateTimeOffset.UtcNow; appDbContext.AvatarInfos.UpdateAndSave(entity); } } @@ -221,7 +221,7 @@ internal sealed partial class AvatarInfoDbBulkOperation EnkaAvatarInfo avatarInfo = new() { AvatarId = avatarId }; transformer.Transform(ref avatarInfo, source); entity = EntityAvatarInfo.From(uid, avatarInfo); - entity.GameRecordRefreshTime = DateTimeOffset.Now; + entity.GameRecordRefreshTime = DateTimeOffset.UtcNow; appDbContext.AvatarInfos.AddAndSave(entity); } else @@ -229,7 +229,7 @@ internal sealed partial class AvatarInfoDbBulkOperation EnkaAvatarInfo avatarInfo = entity.Info; transformer.Transform(ref avatarInfo, source); entity.Info = avatarInfo; - entity.GameRecordRefreshTime = DateTimeOffset.Now; + entity.GameRecordRefreshTime = DateTimeOffset.UtcNow; appDbContext.AvatarInfos.UpdateAndSave(entity); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs index 5eb55a20..c9bd0500 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs @@ -80,13 +80,13 @@ internal sealed class SummaryAvatarFactory // times ShowcaseRefreshTimeFormat = showcaseRefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime ? SH.ServiceAvatarInfoSummaryShowcaseNotRefreshed - : SH.ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat.Format(showcaseRefreshTime), + : SH.FormatServiceAvatarInfoSummaryShowcaseRefreshTimeFormat(showcaseRefreshTime.ToLocalTime()), GameRecordRefreshTimeFormat = gameRecordRefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime ? SH.ServiceAvatarInfoSummaryGameRecordNotRefreshed - : SH.ServiceAvatarInfoSummaryGameRecordRefreshTimeFormat.Format(gameRecordRefreshTime), + : SH.FormatServiceAvatarInfoSummaryGameRecordRefreshTimeFormat(gameRecordRefreshTime.ToLocalTime()), CalculatorRefreshTimeFormat = calculatorRefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime ? SH.ServiceAvatarInfoSummaryCalculatorNotRefreshed - : SH.ServiceAvatarInfoSummaryCalculatorRefreshTimeFormat.Format(calculatorRefreshTime), + : SH.FormatServiceAvatarInfoSummaryCalculatorRefreshTimeFormat(calculatorRefreshTime.ToLocalTime()), }; ApplyCostumeIconOrDefault(ref propertyAvatar, avatar); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotificationOperation.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotificationOperation.cs index a8000ab8..cf96c8ab 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotificationOperation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotificationOperation.cs @@ -139,7 +139,7 @@ internal sealed partial class DailyNoteNotificationOperation SH.ServiceDailyNoteNotifierResin, Web.HutaoEndpoints.StaticFile("ItemIcon", "UI_ItemIcon_210.png"), $"{entry.DailyNote.CurrentResin}", - SH.ServiceDailyNoteNotifierResinCurrent.Format(entry.DailyNote.CurrentResin))); + SH.FormatServiceDailyNoteNotifierResinCurrent(entry.DailyNote.CurrentResin))); entry.ResinNotifySuppressed = true; } } @@ -160,7 +160,7 @@ internal sealed partial class DailyNoteNotificationOperation SH.ServiceDailyNoteNotifierHomeCoin, Web.HutaoEndpoints.StaticFile("ItemIcon", "UI_ItemIcon_204.png"), $"{entry.DailyNote.CurrentHomeCoin}", - SH.ServiceDailyNoteNotifierHomeCoinCurrent.Format(entry.DailyNote.CurrentHomeCoin))); + SH.FormatServiceDailyNoteNotifierHomeCoinCurrent(entry.DailyNote.CurrentHomeCoin))); entry.HomeCoinNotifySuppressed = true; } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs index c37a0b88..48bda3db 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs @@ -132,7 +132,7 @@ internal sealed partial class GachaStatisticsFactory : IGachaStatisticsFactory default: // ItemId string length not correct. - ThrowHelper.UserdataCorrupted(SH.ServiceGachaStatisticsFactoryItemIdInvalid.Format(item.ItemId), default!); + ThrowHelper.UserdataCorrupted(SH.FormatServiceGachaStatisticsFactoryItemIdInvalid(item.ItemId), default!); break; } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HutaoStatisticsFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HutaoStatisticsFactory.cs index c9e1064c..feae8b55 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HutaoStatisticsFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HutaoStatisticsFactory.cs @@ -26,7 +26,7 @@ internal sealed class HutaoStatisticsFactory // TODO: when in new verion // due to lack of newer metadata // this can crash - DateTimeOffset now = DateTimeOffset.Now; + DateTimeOffset now = DateTimeOffset.UtcNow; avatarEvent = context.GachaEvents.Single(g => g.From < now && g.To > now && g.Type == GachaConfigType.AvatarEventWish); avatarEvent2 = context.GachaEvents.Single(g => g.From < now && g.To > now && g.Type == GachaConfigType.AvatarEventWish2); weaponEvent = context.GachaEvents.Single(g => g.From < now && g.To > now && g.Type == GachaConfigType.WeaponEventWish); @@ -55,7 +55,7 @@ internal sealed class HutaoStatisticsFactory { 8U => context.IdAvatarMap[item.Item], 5U => context.IdWeaponMap[item.Item], - _ => throw ThrowHelper.UserdataCorrupted(SH.ServiceGachaStatisticsFactoryItemIdInvalid.Format(item.Item), default!), + _ => throw ThrowHelper.UserdataCorrupted(SH.FormatServiceGachaStatisticsFactoryItemIdInvalid(item.Item), default!), }; StatisticsItem statisticsItem = source.ToStatisticsItem(unchecked((int)item.Count)); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogDbService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogDbService.cs index e6d6d1a5..cfa27516 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogDbService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogDbService.cs @@ -30,7 +30,7 @@ internal sealed partial class GachaLogDbService : IGachaLogDbService } catch (SqliteException ex) { - string message = SH.ServiceGachaLogArchiveCollectionUserdataCorruptedMessage.Format(ex.Message); + string message = SH.FormatServiceGachaLogArchiveCollectionUserdataCorruptedMessage(ex.Message); throw ThrowHelper.UserdataCorrupted(message, ex); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogFetchStatus.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogFetchStatus.cs index c77de33c..a01c15c4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogFetchStatus.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogFetchStatus.cs @@ -41,7 +41,7 @@ internal sealed class GachaLogFetchStatus { return AuthKeyTimeout ? SH.ViewDialogGachaLogRefreshProgressAuthkeyTimeout - : SH.ViewDialogGachaLogRefreshProgressDescription.Format(ConfigType.GetLocalizedDescription()); + : SH.FormatViewDialogGachaLogRefreshProgressDescription(ConfigType.GetLocalizedDescription()); } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryManualInputProvider.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryManualInputProvider.cs index ee2bd7af..a146c2d3 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryManualInputProvider.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryManualInputProvider.cs @@ -39,8 +39,7 @@ internal sealed partial class GachaLogQueryManualInputProvider : IGachaLogQueryP } else { - string message = SH.ServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale - .Format(queryLanguageCode, metadataOptions.LanguageCode); + string message = SH.FormatServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale(queryLanguageCode, metadataOptions.LanguageCode); return new(false, message); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs index f19565ad..b36ce4a4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs @@ -5,6 +5,7 @@ using Snap.Hutao.Core.IO; using Snap.Hutao.Service.Game; using Snap.Hutao.Service.Metadata; using System.Collections.Specialized; +using System.Globalization; using System.IO; using System.Text; using System.Text.RegularExpressions; @@ -70,7 +71,8 @@ internal sealed partial class GachaLogQueryWebCacheProvider : IGachaLogQueryProv { if (!tempFile.TryGetValue(out TempFile file)) { - return new(false, Regex.Unescape(SH.ServiceGachaLogUrlProviderCachePathNotFound).Format(cacheFile)); + string unescaped = Regex.Unescape(SH.ServiceGachaLogUrlProviderCachePathNotFound); + return new(false, string.Format(CultureInfo.CurrentCulture, unescaped, cacheFile)); } using (FileStream fileStream = new(file.Path, FileMode.Open, FileAccess.Read, FileShare.Read)) @@ -93,8 +95,7 @@ internal sealed partial class GachaLogQueryWebCacheProvider : IGachaLogQueryProv return new(true, new(result)); } - string message = SH.ServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale - .Format(queryLanguageCode, metadataOptions.LanguageCode); + string message = SH.FormatServiceGachaLogUrlProviderUrlLanguageNotMatchCurrentLocale(queryLanguageCode, metadataOptions.LanguageCode); return new(false, message); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFImportService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFImportService.cs index b2ca3001..ed63e016 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFImportService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/UIGFImportService.cs @@ -39,13 +39,13 @@ internal sealed partial class UIGFImportService : IUIGFImportService { if (!metadataOptions.IsCurrentLocale(uigf.Info.Language)) { - string message = SH.ServiceGachaUIGFImportLanguageNotMatch.Format(uigf.Info.Language, metadataOptions.LanguageCode); + string message = SH.FormatServiceGachaUIGFImportLanguageNotMatch(uigf.Info.Language, metadataOptions.LanguageCode); ThrowHelper.InvalidOperation(message); } if (!uigf.IsMajor2Minor2OrLowerListValid(out long id)) { - string message = SH.ServiceGachaLogUIGFImportItemInvalidFormat.Format(id); + string message = SH.FormatServiceGachaLogUIGFImportItemInvalidFormat(id); ThrowHelper.InvalidOperation(message); } } @@ -54,7 +54,7 @@ internal sealed partial class UIGFImportService : IUIGFImportService { if (!uigf.IsMajor2Minor3OrHigherListValid(out long id)) { - string message = SH.ServiceGachaLogUIGFImportItemInvalidFormat.Format(id); + string message = SH.FormatServiceGachaLogUIGFImportItemInvalidFormat(id); ThrowHelper.InvalidOperation(message); } } @@ -98,7 +98,7 @@ internal sealed partial class UIGFImportService : IUIGFImportService // 因此从尾部开始查找 if (currentTypeToAdd.LastOrDefault(item => item.ItemId is 0U) is { } item) { - ThrowHelper.InvalidOperation(SH.ServiceGachaLogUIGFImportItemInvalidFormat.Format(item.Id)); + ThrowHelper.InvalidOperation(SH.FormatServiceGachaLogUIGFImportItemInvalidFormat(item.Id)); } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Configuration/GameChannelOptionsService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Configuration/GameChannelOptionsService.cs index 10d37817..80fd68d3 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Configuration/GameChannelOptionsService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Configuration/GameChannelOptionsService.cs @@ -53,11 +53,11 @@ internal sealed partial class GameChannelOptionsService : IGameChannelOptionsSer } catch (FileNotFoundException ex) { - ThrowHelper.GameFileOperation(SH.ServiceGameSetMultiChannelConfigFileNotFound.Format(configPath), ex); + ThrowHelper.GameFileOperation(SH.FormatServiceGameSetMultiChannelConfigFileNotFound(configPath), ex); } catch (DirectoryNotFoundException ex) { - ThrowHelper.GameFileOperation(SH.ServiceGameSetMultiChannelConfigFileNotFound.Format(configPath), ex); + ThrowHelper.GameFileOperation(SH.FormatServiceGameSetMultiChannelConfigFileNotFound(configPath), ex); } catch (UnauthorizedAccessException ex) { diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameFileOperationException.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameFileOperationException.cs index d15a618e..cc5c6fc4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameFileOperationException.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameFileOperationException.cs @@ -15,7 +15,7 @@ internal sealed class GameFileOperationException : Exception /// 消息 /// 内部错误 public GameFileOperationException(string message, Exception? innerException) - : base(SH.ServiceGameFileOperationExceptionMessage.Format(message), innerException) + : base(SH.FormatServiceGameFileOperationExceptionMessage(message), innerException) { } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverter.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverter.cs index 3377193f..65098687 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverter.cs @@ -8,6 +8,7 @@ using Snap.Hutao.Core.IO; using Snap.Hutao.Core.IO.Hashing; using Snap.Hutao.Service.Game.Scheme; using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher; +using System.Globalization; using System.IO; using System.IO.Compression; using System.Net.Http; @@ -236,7 +237,7 @@ internal sealed partial class PackageConverter private async ValueTask SkipOrDownloadAsync(ItemOperationInfo info, PackageConvertContext context, IProgress progress) { // 还原正确的远程地址 - string remoteName = info.Remote.RelativePath.Format(context.ToDataFolderName); + string remoteName = string.Format(CultureInfo.CurrentCulture, info.Remote.RelativePath, context.ToDataFolderName); string cacheFile = context.GetServerCacheTargetFilePath(remoteName); if (File.Exists(cacheFile)) @@ -283,7 +284,7 @@ internal sealed partial class PackageConverter { // System.IO.IOException: The response ended prematurely. // System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream. - ThrowHelper.PackageConvert(SH.ServiceGamePackageRequestScatteredFileFailed.Format(remoteName), ex); + ThrowHelper.PackageConvert(SH.FormatServiceGamePackageRequestScatteredFileFailed(remoteName), ex); } } } @@ -306,8 +307,8 @@ internal sealed partial class PackageConverter // 先备份 if (moveToBackup) { - string localFileName = info.Local.RelativePath.Format(context.FromDataFolderName); - progress.Report(new(SH.ServiceGamePackageConvertMoveFileBackupFormat.Format(localFileName))); + string localFileName = string.Format(CultureInfo.CurrentCulture, info.Local.RelativePath, context.FromDataFolderName); + progress.Report(new(SH.FormatServiceGamePackageConvertMoveFileBackupFormat(localFileName))); string localFilePath = context.GetGameFolderFilePath(localFileName); string cacheFilePath = context.GetServerCacheBackupFilePath(localFileName); @@ -322,8 +323,8 @@ internal sealed partial class PackageConverter // 后替换 if (moveToTarget) { - string targetFileName = info.Remote.RelativePath.Format(context.ToDataFolderName); - progress.Report(new(SH.ServiceGamePackageConvertMoveFileRestoreFormat.Format(targetFileName))); + string targetFileName = string.Format(CultureInfo.CurrentCulture, info.Remote.RelativePath, context.ToDataFolderName); + progress.Report(new(SH.FormatServiceGamePackageConvertMoveFileRestoreFormat(targetFileName))); string targetFilePath = context.GetGameFolderFilePath(targetFileName); string? targetFileDirectory = Path.GetDirectoryName(targetFilePath); @@ -339,7 +340,7 @@ internal sealed partial class PackageConverter // 重命名 _Data 目录 try { - progress.Report(new(SH.ServiceGamePackageConvertMoveFileRenameFormat.Format(context.FromDataFolderName, context.ToDataFolderName))); + progress.Report(new(SH.FormatServiceGamePackageConvertMoveFileRenameFormat(context.FromDataFolderName, context.ToDataFolderName))); DirectoryOperation.Move(context.FromDataFolder, context.ToDataFolder); } catch (IOException ex) diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoAsAService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoAsAService.cs index 28a52a4e..40963af4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoAsAService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoAsAService.cs @@ -54,13 +54,13 @@ internal sealed partial class HutaoAsAService : IHutaoAsAService foreach ((string key, object value) in excludedIds) { - if (value is DateTimeOffset time && time < DateTimeOffset.Now - TimeSpan.FromDays(AnnouncementDuration)) + if (value is DateTimeOffset time && time < DateTimeOffset.UtcNow - TimeSpan.FromDays(AnnouncementDuration)) { excludedIds.Remove(key); } } - excludedIds.TryAdd($"{announcement.Id}", DateTimeOffset.Now + TimeSpan.FromDays(AnnouncementDuration)); + excludedIds.TryAdd($"{announcement.Id}", DateTimeOffset.UtcNow + TimeSpan.FromDays(AnnouncementDuration)); LocalSetting.Set(SettingKeys.ExcludedAnnouncementIds, excludedIds); announcements.Remove(announcement); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoCache.cs b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoCache.cs index 9ed938c0..c5c049da 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoCache.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoCache.cs @@ -184,7 +184,7 @@ internal sealed partial class HutaoCache : IHutaoCache AvatarAppearanceRanks = avatarAppearanceRanksRaw.SortByDescending(r => r.Floor).SelectList(rank => new AvatarRankView { - Floor = SH.ModelBindingHutaoComplexRankFloor.Format(rank.Floor), + Floor = SH.FormatModelBindingHutaoComplexRankFloor(rank.Floor), Avatars = rank.Ranks.SortByDescending(r => r.Rate).SelectList(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)), }); } @@ -201,7 +201,7 @@ internal sealed partial class HutaoCache : IHutaoCache AvatarUsageRanks = avatarUsageRanksRaw.SortByDescending(r => r.Floor).SelectList(rank => new AvatarRankView { - Floor = SH.ModelBindingHutaoComplexRankFloor.Format(rank.Floor), + Floor = SH.FormatModelBindingHutaoComplexRankFloor(rank.Floor), Avatars = rank.Ranks.SortByDescending(r => r.Rate).SelectList(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)), }); } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs index f8db2272..87074a42 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs @@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using Microsoft.Extensions.Options; using Snap.Hutao.Core.Setting; using Snap.Hutao.Web.Hutao; +using System.Globalization; using System.Text.RegularExpressions; namespace Snap.Hutao.Service.Hutao; @@ -118,9 +119,10 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions DateTimeOffset.Now; + IsCloudServiceAllowed = IsLicensedDeveloper || userInfo.GachaLogExpireAt > DateTimeOffset.UtcNow; } public async ValueTask GetTokenAsync() diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/ObjectCacheDbService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/ObjectCacheDbService.cs index 8e61bf18..f93c7eeb 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/ObjectCacheDbService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/ObjectCacheDbService.cs @@ -25,7 +25,7 @@ internal sealed partial class ObjectCacheDbService : IObjectCacheDbService await appDbContext.ObjectCache.AddAndSaveAsync(new() { Key = key, - ExpireTime = DateTimeOffset.Now.Add(expire), + ExpireTime = DateTimeOffset.UtcNow.Add(expire), Value = JsonSerializer.Serialize(data, jsonSerializerOptions), }).ConfigureAwait(false); } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/SignIn/SignInService.cs b/src/Snap.Hutao/Snap.Hutao/Service/SignIn/SignInService.cs index 62d23daf..18d690c4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/SignIn/SignInService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/SignIn/SignInService.cs @@ -33,7 +33,7 @@ internal sealed partial class SignInService : ISignInService { int index = infoResponse.Data.TotalSignDay - 1; Award award = rewardResponse.Data.Awards[index]; - return new(true, SH.ServiceSignInSuccessRewardFormat.Format(award.Name, award.Count)); + return new(true, SH.FormatServiceSignInSuccessRewardFormat(award.Name, award.Count)); } else { @@ -54,7 +54,7 @@ internal sealed partial class SignInService : ISignInService message = $"RiskCode: {resultResponse.Data?.RiskCode}"; } - return new(false, SH.ServiceSignInClaimRewardFailedFormat.Format(message)); + return new(false, SH.FormatServiceSignInClaimRewardFailedFormat(message)); } } else diff --git a/src/Snap.Hutao/Snap.Hutao/Service/User/UserFingerprintService.cs b/src/Snap.Hutao/Snap.Hutao/Service/User/UserFingerprintService.cs index 123160db..4a2be536 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/User/UserFingerprintService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/User/UserFingerprintService.cs @@ -68,7 +68,7 @@ internal sealed partial class UserFingerprintService : IUserFingerprintService DeviceId = Core.Random.GetLowerHexString(16), SeedId = $"{Guid.NewGuid()}", Platform = "2", - SeedTime = $"{DateTimeOffset.Now.ToUnixTimeMilliseconds()}", + SeedTime = $"{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}", ExtFields = JsonSerializer.Serialize(extendProperties), AppName = "bbs_cn", BbsDeviceId = HoyolabOptions.DeviceId, diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 7a5f42e4..0604b25b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -310,6 +310,10 @@ + + + + diff --git a/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs index 945f5f13..3eea5f49 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs @@ -25,20 +25,16 @@ internal sealed partial class TitleView : UserControl /// /// 标题 /// - [SuppressMessage("", "CA1822")] public string Title { + [SuppressMessage("", "IDE0027")] get { - Core.RuntimeOptions hutaoOptions = Ioc.Default.GetRequiredService(); - - string format = #if DEBUG - SH.AppDevNameAndVersion; + return SH.FormatAppDevNameAndVersion(RuntimeOptions.Version); #else - SH.AppNameAndVersion; + return SH.FormatAppNameAndVersion(RuntimeOptions.Version); #endif - return format.Format(hutaoOptions.Version); } } @@ -50,15 +46,7 @@ internal sealed partial class TitleView : UserControl get => DragableGrid; } - [SuppressMessage("", "CA1822")] - public RuntimeOptions RuntimeOptions - { - get => Ioc.Default.GetRequiredService(); - } + public RuntimeOptions RuntimeOptions { get; } = Ioc.Default.GetRequiredService(); - [SuppressMessage("", "CA1822")] - public HotKeyOptions HotKeyOptions - { - get => Ioc.Default.GetRequiredService(); - } + public HotKeyOptions HotKeyOptions { get; } = Ioc.Default.GetRequiredService(); } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementView.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementView.cs index a3b0bdbf..d35b851e 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementView.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementView.cs @@ -54,7 +54,7 @@ internal sealed class AchievementView : ObservableObject, IEntityWithMetadata public string Time { - get => $"{Entity.Time:yyyy.MM.dd HH:mm:ss}"; + get => $"{Entity.Time.ToLocalTime():yyyy.MM.dd HH:mm:ss}"; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs index aa69f253..f4fd36c3 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs @@ -206,13 +206,13 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav case ArchiveAddResult.Added: await taskContext.SwitchToMainThreadAsync(); SelectedArchive = achievementService.CurrentArchive; - infoBarService.Success(SH.ViewModelAchievementArchiveAdded.Format(name)); + infoBarService.Success(SH.FormatViewModelAchievementArchiveAdded(name)); break; case ArchiveAddResult.InvalidName: infoBarService.Warning(SH.ViewModelAchievementArchiveInvalidName); break; case ArchiveAddResult.AlreadyExists: - infoBarService.Warning(SH.ViewModelAchievementArchiveAlreadyExists.Format(name)); + infoBarService.Warning(SH.FormatViewModelAchievementArchiveAlreadyExists(name)); break; default: throw Must.NeverHappen(); @@ -226,7 +226,7 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav { if (Archives is not null && SelectedArchive is not null) { - string title = SH.ViewModelAchievementRemoveArchiveTitle.Format(SelectedArchive.Name); + string title = SH.FormatViewModelAchievementRemoveArchiveTitle(SelectedArchive.Name); string content = SH.ViewModelAchievementRemoveArchiveContent; ContentDialogResult result = await contentDialogFactory .CreateForConfirmCancelAsync(title, content) diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModel.cs index b255e05d..cf249276 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModel.cs @@ -322,11 +322,11 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I if (result.Interrupted) { infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning); - infoBarService.Warning(SH.ViewModelCultivationBatchAddIncompletedFormat.Format(result.SucceedCount, result.SkippedCount)); + infoBarService.Warning(SH.FormatViewModelCultivationBatchAddIncompletedFormat(result.SucceedCount, result.SkippedCount)); } else { - infoBarService.Success(SH.ViewModelCultivationBatchAddCompletedFormat.Format(result.SucceedCount, result.SkippedCount)); + infoBarService.Success(SH.FormatViewModelCultivationBatchAddCompletedFormat(result.SucceedCount, result.SkippedCount)); } } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/WeaponView.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/WeaponView.cs index 8bfb46c7..495b0b9d 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/WeaponView.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/WeaponView.cs @@ -26,7 +26,7 @@ internal sealed class WeaponView : Equip, ICalculableSource /// /// 精炼属性 /// - public string AffixLevel { get => SH.ModelBindingAvatarPropertyWeaponAffixFormat.Format(AffixLevelNumber); } + public string AffixLevel { get => SH.FormatModelBindingAvatarPropertyWeaponAffixFormat(AffixLevelNumber); } /// /// 精炼名称 diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Complex/Team.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Complex/Team.cs index 59c8e45a..37006714 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Complex/Team.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Complex/Team.cs @@ -29,7 +29,7 @@ internal sealed class Team : List Add(new(idAvatarMap[id])); } - Rate = SH.ModelBindingHutaoTeamUpCountFormat.Format(team.Rate); + Rate = SH.FormatModelBindingHutaoTeamUpCountFormat(team.Rate); } /// diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Complex/TeamAppearanceView.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Complex/TeamAppearanceView.cs index c914b6ed..58ff9c2c 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Complex/TeamAppearanceView.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Complex/TeamAppearanceView.cs @@ -20,7 +20,7 @@ internal sealed class TeamAppearanceView /// 映射 public TeamAppearanceView(TeamAppearance teamRank, Dictionary idAvatarMap) { - Floor = SH.ModelBindingHutaoComplexRankFloor.Format(teamRank.Floor); + Floor = SH.FormatModelBindingHutaoComplexRankFloor(teamRank.Floor); Up = teamRank.Up.SelectList(teamRate => new Team(teamRate, idAvatarMap)); Down = teamRank.Down.SelectList(teamRate => new Team(teamRate, idAvatarMap)); } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModel.cs index 52cefc4f..478ba2e7 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModel.cs @@ -270,7 +270,7 @@ internal sealed partial class GachaLogViewModel : Abstraction.ViewModel if (Archives is not null && SelectedArchive is not null) { ContentDialogResult result = await contentDialogFactory - .CreateForConfirmCancelAsync(SH.ViewModelGachaLogRemoveArchiveTitle.Format(SelectedArchive.Uid), SH.ViewModelGachaLogRemoveArchiveDescription) + .CreateForConfirmCancelAsync(SH.FormatViewModelGachaLogRemoveArchiveTitle(SelectedArchive.Uid), SH.ViewModelGachaLogRemoveArchiveDescription) .ConfigureAwait(false); if (result == ContentDialogResult.Primary) diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/TypedWishSummary.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/TypedWishSummary.cs index b74c20e2..3e9202e5 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/TypedWishSummary.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/TypedWishSummary.cs @@ -28,7 +28,7 @@ internal sealed partial class TypedWishSummary : Wish /// public string MaxOrangePullFormatted { - get => SH.ModelBindingGachaTypedWishSummaryMaxOrangePullFormat.Format(MaxOrangePull); + get => SH.FormatModelBindingGachaTypedWishSummaryMaxOrangePullFormat(MaxOrangePull); } /// @@ -36,7 +36,7 @@ internal sealed partial class TypedWishSummary : Wish /// public string MinOrangePullFormatted { - get => SH.ModelBindingGachaTypedWishSummaryMinOrangePullFormat.Format(MinOrangePull); + get => SH.FormatModelBindingGachaTypedWishSummaryMinOrangePullFormat(MinOrangePull); } /// @@ -88,7 +88,7 @@ internal sealed partial class TypedWishSummary : Wish /// public string AverageOrangePullFormatted { - get => SH.ModelBindingGachaTypedWishSummaryAveragePullFormat.Format(AverageOrangePull); + get => SH.FormatModelBindingGachaTypedWishSummaryAveragePullFormat(AverageOrangePull); } /// @@ -101,7 +101,7 @@ internal sealed partial class TypedWishSummary : Wish /// public string AverageUpOrangePullFormatted { - get => SH.ModelBindingGachaTypedWishSummaryAveragePullFormat.Format(AverageUpOrangePull); + get => SH.FormatModelBindingGachaTypedWishSummaryAveragePullFormat(AverageUpOrangePull); } /// @@ -109,7 +109,7 @@ internal sealed partial class TypedWishSummary : Wish /// public string PredictedPullLeftToOrangeFormatted { - get => SH.ViewModelGachaLogPredictedPullLeftToOrange.Format(PredictedPullLeftToOrange, ProbabilityOfPredictedPullLeftToOrange); + get => SH.FormatViewModelGachaLogPredictedPullLeftToOrange(PredictedPullLeftToOrange, ProbabilityOfPredictedPullLeftToOrange); } /// @@ -117,7 +117,7 @@ internal sealed partial class TypedWishSummary : Wish /// public string ProbabilityOfNextPullIsOrangeFormatted { - get => SH.ViewModelGachaLogProbabilityOfNextPullIsOrange.Format(ProbabilityOfNextPullIsOrange); + get => SH.FormatViewModelGachaLogProbabilityOfNextPullIsOrange(ProbabilityOfNextPullIsOrange); } /// diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/Wish.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/Wish.cs index fc5278c0..978e81af 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/Wish.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/Wish.cs @@ -29,7 +29,7 @@ internal abstract class Wish /// public string TotalCountFormatted { - get => SH.ModelBindingGachaWishBaseTotalCountFormat.Format(TotalCount); + get => SH.FormatModelBindingGachaWishBaseTotalCountFormat(TotalCount); } /// diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs index 02a5e442..c80f600a 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs @@ -138,7 +138,7 @@ internal sealed partial class LaunchGameViewModel : Abstraction.ViewModel } else { - infoBarService.Warning(SH.ViewModelLaunchGameMultiChannelReadFail.Format(options.ConfigFilePath)); + infoBarService.Warning(SH.FormatViewModelLaunchGameMultiChannelReadFail(options.ConfigFilePath)); } ObservableCollection accounts = gameService.GameAccountCollection; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Home/AnnouncementViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Home/AnnouncementViewModel.cs index bf574600..adf63276 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Home/AnnouncementViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Home/AnnouncementViewModel.cs @@ -107,7 +107,7 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel } else if (rand == 1) { - GreetingText = SH.ViewPageHomeGreetingTextCommon2.Format(LocalSetting.Get(SettingKeys.LaunchTimes, 0)); + GreetingText = SH.FormatViewPageHomeGreetingTextCommon2(LocalSetting.Get(SettingKeys.LaunchTimes, 0)); } } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs index d86f50c5..57ffa664 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; using Microsoft.UI.Xaml.Controls; using Microsoft.Windows.AppLifecycle; using Snap.Hutao.Core; @@ -180,7 +179,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel } else { - infoBarService.Warning(SH.ViewModelSettingClearWebCachePathInvalid.Format(cacheFolder)); + infoBarService.Warning(SH.FormatViewModelSettingClearWebCachePathInvalid(cacheFolder)); } } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/FloorView.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/FloorView.cs index 865b2126..9a5e6e3d 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/FloorView.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/FloorView.cs @@ -14,7 +14,7 @@ internal sealed class FloorView : IMappingFrom, /// /// 视图 中使用的计划 Id 字符串 /// - public string Schedule { get => SH.ModelEntitySpiralAbyssScheduleFormat.Format(ScheduleId); } + public string Schedule { get => SH.FormatModelEntitySpiralAbyssScheduleFormat(ScheduleId); } public SpiralAbyssEntry? Entity { get => entity; } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs index 2c8aaec8..f3c31406 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs @@ -85,7 +85,7 @@ internal sealed partial class UserViewModel : ObservableObject SelectedUser = Users.Single(); } - infoBarService.Success(SH.ViewModelUserAdded.Format(uid)); + infoBarService.Success(SH.FormatViewModelUserAdded(uid)); break; case UserOptionResult.Incomplete: infoBarService.Information(SH.ViewModelUserIncomplete); @@ -94,7 +94,7 @@ internal sealed partial class UserViewModel : ObservableObject infoBarService.Information(SH.ViewModelUserInvalid); break; case UserOptionResult.Updated: - infoBarService.Success(SH.ViewModelUserUpdated.Format(uid)); + infoBarService.Success(SH.FormatViewModelUserUpdated(uid)); break; default: throw Must.NeverHappen(); @@ -181,7 +181,7 @@ internal sealed partial class UserViewModel : ObservableObject try { await userService.RemoveUserAsync(user).ConfigureAwait(false); - infoBarService.Success(SH.ViewModelUserRemoved.Format(user.UserInfo?.Nickname)); + infoBarService.Success(SH.FormatViewModelUserRemoved(user.UserInfo?.Nickname)); } catch (UserdataCorruptedException ex) { @@ -206,7 +206,7 @@ internal sealed partial class UserViewModel : ObservableObject serviceProvider.GetRequiredService().SetText(cookieString); ArgumentNullException.ThrowIfNull(user.UserInfo); - infoBarService.Success(SH.ViewModelUserCookieCopied.Format(user.UserInfo.Nickname)); + infoBarService.Success(SH.FormatViewModelUserCookieCopied(user.UserInfo.Nickname)); } catch (Exception ex) { diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Enka/EnkaClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Enka/EnkaClient.cs index 5d318fe1..0d362873 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Enka/EnkaClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Enka/EnkaClient.cs @@ -6,6 +6,7 @@ using Snap.Hutao.Web.Enka.Model; using Snap.Hutao.Web.Hoyolab; using Snap.Hutao.Web.Request.Builder; using Snap.Hutao.Web.Request.Builder.Abstraction; +using System.Globalization; using System.IO; using System.Net; using System.Net.Http; @@ -37,7 +38,7 @@ internal sealed partial class EnkaClient /// Enka API 响应 public ValueTask GetForwardDataAsync(in PlayerUid playerUid, CancellationToken token = default) { - return TryGetEnkaResponseCoreAsync(EnkaAPIHutaoForward.Format(playerUid.Value), token); + return TryGetEnkaResponseCoreAsync(string.Format(CultureInfo.CurrentCulture, EnkaAPIHutaoForward, playerUid.Value), token); } /// @@ -48,7 +49,7 @@ internal sealed partial class EnkaClient /// Enka API 响应 public ValueTask GetDataAsync(in PlayerUid playerUid, CancellationToken token = default) { - return TryGetEnkaResponseCoreAsync(EnkaAPI.Format(playerUid.Value), token); + return TryGetEnkaResponseCoreAsync(string.Format(CultureInfo.CurrentCulture, EnkaAPI, playerUid.Value), token); } private async ValueTask TryGetEnkaResponseCoreAsync(string url, CancellationToken token = default) diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/Announcement.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/Announcement.cs index e9b03136..389caf90 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/Announcement.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/Announcement.cs @@ -35,20 +35,20 @@ internal sealed class Announcement : AnnouncementContent TimeSpan span = StartTime - now; if (span.TotalDays <= 1) { - return SH.WebAnnouncementTimeHoursBeginFormat.Format((int)span.TotalHours); + return SH.FormatWebAnnouncementTimeHoursBeginFormat((int)span.TotalHours); } - return SH.WebAnnouncementTimeDaysBeginFormat.Format((int)span.TotalDays); + return SH.FormatWebAnnouncementTimeDaysBeginFormat((int)span.TotalDays); } else { TimeSpan span = EndTime - now; if (span.TotalDays <= 1) { - return SH.WebAnnouncementTimeHoursEndFormat.Format((int)span.TotalHours); + return SH.FormatWebAnnouncementTimeHoursEndFormat((int)span.TotalHours); } - return SH.WebAnnouncementTimeDaysEndFormat.Format((int)span.TotalDays); + return SH.FormatWebAnnouncementTimeDaysEndFormat((int)span.TotalDays); } } } @@ -68,9 +68,7 @@ internal sealed class Announcement : AnnouncementContent { get { - // TODO: validate correctness - // UTC+8 - DateTimeOffset currentTime = DateTimeOffset.Now; + DateTimeOffset currentTime = DateTimeOffset.UtcNow; TimeSpan current = currentTime - StartTime; TimeSpan total = EndTime - StartTime; return current / total; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/DailyNote.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/DailyNote.cs index a3223d51..f2038ee6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/DailyNote.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/DailyNote.cs @@ -38,10 +38,10 @@ internal sealed class DailyNote : DailyNoteCommon 0 => SH.WebDailyNoteRecoveryTimeDay0, 1 => SH.WebDailyNoteRecoveryTimeDay1, 2 => SH.WebDailyNoteRecoveryTimeDay2, - _ => SH.WebDailyNoteRecoveryTimeDayFormat.Format(totalDays), + _ => SH.FormatWebDailyNoteRecoveryTimeDayFormat(totalDays), }; - return SH.WebDailyNoteResinRecoveryFormat.Format(day, reach); + return SH.FormatWebDailyNoteResinRecoveryFormat(day, reach); } } @@ -129,9 +129,9 @@ internal sealed class DailyNote : DailyNoteCommon 0 => SH.WebDailyNoteRecoveryTimeDay0, 1 => SH.WebDailyNoteRecoveryTimeDay1, 2 => SH.WebDailyNoteRecoveryTimeDay2, - _ => SH.WebDailyNoteRecoveryTimeDayFormat.Format(totalDays), + _ => SH.FormatWebDailyNoteRecoveryTimeDayFormat(totalDays), }; - return SH.WebDailyNoteHomeCoinRecoveryFormat.Format(day, reach); + return SH.FormatWebDailyNoteHomeCoinRecoveryFormat(day, reach); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/Expedition.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/Expedition.cs index 2a6ce1ab..1981bc47 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/Expedition.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/Expedition.cs @@ -81,8 +81,8 @@ internal sealed class Expedition TimeSpan ts = new(0, 0, RemainedTime); return ts.Hours > 0 - ? SH.WebDailyNoteExpeditionRemainHoursFormat.Format(ts.Hours) - : SH.WebDailyNoteExpeditionRemainMinutesFormat.Format(ts.Minutes); + ? SH.FormatWebDailyNoteExpeditionRemainHoursFormat(ts.Hours) + : SH.FormatWebDailyNoteExpeditionRemainMinutesFormat(ts.Minutes); } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/RecoveryTime.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/RecoveryTime.cs index eb526cad..723c94b9 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/RecoveryTime.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/DailyNote/RecoveryTime.cs @@ -67,10 +67,10 @@ internal sealed class RecoveryTime else { return new StringBuilder() - .AppendIf(Day > 0, SH.WebDailyNoteTransformerDaysFormat.Format(Day)) - .AppendIf(Hour > 0, SH.WebDailyNoteTransformerHoursFormat.Format(Hour)) - .AppendIf(Minute > 0, SH.WebDailyNoteTransformerMinutesFormat.Format(Minute)) - .AppendIf(Second > 0, SH.WebDailyNoteTransformerSecondsFormat.Format(Second)) + .AppendIf(Day > 0, SH.FormatWebDailyNoteTransformerDaysFormat(Day)) + .AppendIf(Hour > 0, SH.FormatWebDailyNoteTransformerHoursFormat(Hour)) + .AppendIf(Minute > 0, SH.FormatWebDailyNoteTransformerMinutesFormat(Minute)) + .AppendIf(Second > 0, SH.FormatWebDailyNoteTransformerSecondsFormat(Second)) .Append(SH.WebDailyNoteTransformerAppend) .ToString(); } @@ -92,10 +92,10 @@ internal sealed class RecoveryTime else { return new StringBuilder() - .AppendIf(Day > 0, SH.WebDailyNoteTransformerDaysFormat.Format(Day)) - .AppendIf(Hour > 0, SH.WebDailyNoteTransformerHoursFormat.Format(Hour)) - .AppendIf(Minute > 0, SH.WebDailyNoteTransformerMinutesFormat.Format(Minute)) - .AppendIf(Second > 0, SH.WebDailyNoteTransformerSecondsFormat.Format(Second)) + .AppendIf(Day > 0, SH.FormatWebDailyNoteTransformerDaysFormat(Day)) + .AppendIf(Hour > 0, SH.FormatWebDailyNoteTransformerHoursFormat(Hour)) + .AppendIf(Minute > 0, SH.FormatWebDailyNoteTransformerMinutesFormat(Minute)) + .AppendIf(Second > 0, SH.FormatWebDailyNoteTransformerSecondsFormat(Second)) .ToString(); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Geetest/HomaGeetestClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Geetest/HomaGeetestClient.cs index a36802d3..4f9ba6be 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Geetest/HomaGeetestClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Geetest/HomaGeetestClient.cs @@ -5,6 +5,7 @@ using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; using Snap.Hutao.Service; using Snap.Hutao.Web.Request.Builder; using Snap.Hutao.Web.Request.Builder.Abstraction; +using System.Globalization; using System.Net.Http; namespace Snap.Hutao.Web.Hutao.Geetest; @@ -25,7 +26,7 @@ internal sealed partial class HomaGeetestClient string url; try { - url = template.Format(gt, challenge); + url = string.Format(CultureInfo.CurrentCulture, template, gt, challenge); } catch (FormatException) { diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HutaoResponse.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HutaoResponse.cs index 56397a7f..e73529e0 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HutaoResponse.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HutaoResponse.cs @@ -20,20 +20,20 @@ internal sealed class HutaoResponse : Response.Response, ILocalizableResponse public static HutaoResponse DefaultIfNull(HutaoResponse? response, [CallerMemberName] string callerName = default!) { // 0x26F19335 is a magic number that hashed from "Snap.Hutao" - response ??= new(InternalFailure, SH.WebResponseRequestExceptionFormat.Format(callerName, null), default); + response ??= new(InternalFailure, SH.FormatWebResponseRequestExceptionFormat(callerName, null), default); return response; } public static HutaoResponse DefaultIfNull(HutaoResponse? response, [CallerMemberName] string callerName = default!) { // 0x26F19335 is a magic number that hashed from "Snap.Hutao" - response ??= new(InternalFailure, SH.WebResponseRequestExceptionFormat.Format(callerName, typeof(TData).Name), default, default); - return response ?? new(InternalFailure, SH.WebResponseRequestExceptionFormat.Format(callerName, typeof(TData).Name), default, default); + response ??= new(InternalFailure, SH.FormatWebResponseRequestExceptionFormat(callerName, typeof(TData).Name), default, default); + return response ?? new(InternalFailure, SH.FormatWebResponseRequestExceptionFormat(callerName, typeof(TData).Name), default, default); } public override string ToString() { - return SH.WebResponseFormat.Format(ReturnCode, this.GetLocalizationMessageOrDefault()); + return SH.FormatWebResponseFormat(ReturnCode, this.GetLocalizationMessageOrDefault()); } } @@ -52,6 +52,6 @@ internal sealed class HutaoResponse : Response.Response, ILocaliza public override string ToString() { - return SH.WebResponseFormat.Format(ReturnCode, this.GetLocalizationMessageOrDefault()); + return SH.FormatWebResponseFormat(ReturnCode, this.GetLocalizationMessageOrDefault()); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Log/HomaLogUploadClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Log/HomaLogUploadClient.cs index 7574e59b..30d110e4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Log/HomaLogUploadClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Log/HomaLogUploadClient.cs @@ -46,7 +46,7 @@ internal sealed partial class HomaLogUploadClient return new() { Id = runtimeOptions.DeviceId, - Time = DateTimeOffset.Now.ToUnixTimeMilliseconds(), + Time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), Info = Core.ExceptionService.ExceptionFormat.Format(exception), }; } diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Response/Response.cs b/src/Snap.Hutao/Snap.Hutao/Web/Response/Response.cs index 30697bca..4f0bc8b8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Response/Response.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Response/Response.cs @@ -56,11 +56,11 @@ internal class Response public static Response DefaultIfNull(Response? response, [CallerMemberName] string callerName = default!) { // 0x26F19335 is a magic number that hashed from "Snap.Hutao" - response ??= new(InternalFailure, SH.WebResponseRequestExceptionFormat.Format(callerName, null)); + response ??= new(InternalFailure, SH.FormatWebResponseRequestExceptionFormat(callerName, null)); if (((KnownReturnCode)response.ReturnCode) is KnownReturnCode.PleaseLogin or KnownReturnCode.RET_TOKEN_INVALID) { - response.Message = SH.WebResponseRefreshCookieHintFormat.Format(response.Message); + response.Message = SH.FormatWebResponseRefreshCookieHintFormat(response.Message); } return response; @@ -76,14 +76,14 @@ internal class Response public static Response DefaultIfNull(Response? response, [CallerMemberName] string callerName = default!) { // 0x26F19335 is a magic number that hashed from "Snap.Hutao" - response ??= new(InternalFailure, SH.WebResponseRequestExceptionFormat.Format(callerName, typeof(TData).Name), default); + response ??= new(InternalFailure, SH.FormatWebResponseRequestExceptionFormat(callerName, typeof(TData).Name), default); if (((KnownReturnCode)response.ReturnCode) is KnownReturnCode.PleaseLogin or KnownReturnCode.RET_TOKEN_INVALID) { - response.Message = SH.WebResponseRefreshCookieHintFormat.Format(response.Message); + response.Message = SH.FormatWebResponseRefreshCookieHintFormat(response.Message); } - return response ?? new(InternalFailure, SH.WebResponseRequestExceptionFormat.Format(callerName, typeof(TData).Name), default); + return response ?? new(InternalFailure, SH.FormatWebResponseRequestExceptionFormat(callerName, typeof(TData).Name), default); } /// @@ -104,7 +104,7 @@ internal class Response else { // Magic number that hashed from "Snap.Hutao" - return new(InternalFailure, SH.WebResponseRequestExceptionFormat.Format(callerName, typeof(TData).Name), default); + return new(InternalFailure, SH.FormatWebResponseRequestExceptionFormat(callerName, typeof(TData).Name), default); } } @@ -129,7 +129,7 @@ internal class Response /// public override string ToString() { - return SH.WebResponseFormat.Format(ReturnCode, Message); + return SH.FormatWebResponseFormat(ReturnCode, Message); } }