From cd066e14621c2e57e88b8a43abd92c0418f7c697 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Tue, 18 Jul 2023 16:54:42 +0800 Subject: [PATCH] mapping abstraction --- src/Snap.Hutao/Snap.Hutao/App.xaml.cs | 2 +- .../Control/Image/CompositionImage.cs | 4 +- .../Core/Abstraction/IMappingFrom.cs | 20 +++++++ .../Snap.Hutao/Core/Caching/ImageCache.cs | 2 +- .../DependencyInjection/IocConfiguration.cs | 2 +- .../IocHttpClientConfiguration.cs | 2 +- .../Core/LifeCycle/AppInstanceExtension.cs | 2 + .../{HutaoOptions.cs => RuntimeOptions.cs} | 17 ++++-- .../Snap.Hutao/Core/Setting/FeatureOptions.cs | 6 +- .../Snap.Hutao/Core/Setting/SettingKeys.cs | 31 ---------- .../Snap.Hutao/Core/Setting/StaticResource.cs | 44 ++++++++++++--- .../ConcurrentCancellationTokenSource.cs | 29 ---------- .../Core/Threading/SemaphoreSlimToken.cs | 6 +- .../Snap.Hutao/Core/Threading/TaskContext.cs | 2 +- .../Core/Threading/TaskExtension.cs | 10 ++-- .../Snap.Hutao/Core/Validation/Must.cs | 15 ----- .../Core/Windowing/ExtendedWindow.cs | 6 +- .../Snap.Hutao/Core/Windowing/Persistence.cs | 36 +----------- .../Core/Windowing/WindowOptions.cs | 34 +++++++++++ .../Core/Windowing/WindowSubclass.cs | 3 +- .../EnumerableExtension.Dictionary.cs | 6 +- .../Extension/EnumerableExtension.cs | 1 + .../Snap.Hutao/Extension/ObjectExtension.cs | 3 +- .../Abstraction/IContentDialogFactory.cs | 4 +- .../Factory/ContentDialogFactory.cs | 56 +++++++------------ .../Snap.Hutao/Factory/PickerFactory.cs | 19 ++----- .../Model/Calculable/CalculableAvatar.cs | 22 +++++++- .../Model/Calculable/CalculableOptions.cs | 22 ++++---- .../Model/Calculable/CalculableSkill.cs | 21 ++++++- .../Model/Calculable/CalculableWeapon.cs | 22 +++++++- .../Abstraction/IDbMappingForeignKeyFrom.cs | 18 ++++++ .../Snap.Hutao/Model/Entity/Achievement.cs | 33 +++++------ .../Model/Entity/AchievementArchive.cs | 5 +- .../Snap.Hutao/Model/Entity/AvatarInfo.cs | 7 ++- .../Configuration/AvatarInfoConfiguration.cs | 2 +- .../DailyNoteEntryConfiguration.cs | 2 +- .../InventoryReliquaryConfiguration.cs | 2 +- .../SpiralAbyssEntryConfiguration.cs | 2 +- .../Entity/Configuration/SqliteTypeNames.cs | 12 ++++ .../Entity/Configuration/UserConfiguration.cs | 6 +- .../Snap.Hutao/Model/Entity/CultivateEntry.cs | 5 +- .../Snap.Hutao/Model/Entity/CultivateItem.cs | 12 ++-- .../Model/Entity/CultivateProject.cs | 5 +- .../Snap.Hutao/Model/Entity/DailyNoteEntry.cs | 5 +- .../Snap.Hutao/Model/Entity/GachaArchive.cs | 7 ++- .../Model/InterChange/Achievement/UIAFInfo.cs | 2 +- .../Model/InterChange/Achievement/UIAFItem.cs | 14 ++++- .../Model/InterChange/GachaLog/UIGFInfo.cs | 2 +- .../Model/InterChange/Inventory/UIIFInfo.cs | 2 +- .../Metadata/Avatar/Avatar.Implementation.cs | 2 +- .../Avatar/ProudableSkill.Implementation.cs | 2 +- .../Metadata/Weapon/Weapon.Implementation.cs | 2 +- .../Achievement/AchievementDbBulkOperation.cs | 6 +- .../AchievementService.Interchange.cs | 4 +- .../Service/Achievement/AchievementService.cs | 2 +- .../AvatarInfo/AvatarInfoDbBulkOperation.cs | 4 +- .../Service/Cultivation/CultivationService.cs | 4 +- .../Service/DailyNote/DailyNoteService.cs | 2 +- .../Service/GachaLog/HutaoCloudService.cs | 2 +- .../Snap.Hutao/Service/Game/GameService.cs | 6 +- .../Service/Game/Package/PackageConverter.cs | 2 +- .../Service/Metadata/MetadataOptions.cs | 2 +- .../Metadata/MetadataService.Indexing.cs | 3 +- .../Service/Metadata/MetadataService.cs | 16 ++++-- .../Service/Navigation/NavigationService.cs | 3 +- .../Dialog/CultivateProjectDialog.xaml.cs | 2 +- .../Snap.Hutao/View/TitleView.xaml.cs | 2 +- .../Achievement/AchievementViewModel.cs | 4 +- .../ViewModel/AvatarProperty/AvatarView.cs | 2 +- .../ViewModel/AvatarProperty/SkillView.cs | 2 +- .../ViewModel/AvatarProperty/WeaponView.cs | 2 +- .../ExperimentalFeaturesViewModel.cs | 6 +- .../ViewModel/GachaLog/GachaLogViewModel.cs | 4 +- .../ViewModel/Game/LaunchGameViewModel.cs | 4 +- .../Snap.Hutao/ViewModel/SettingViewModel.cs | 4 +- .../ViewModel/User/UserViewModel.cs | 2 +- .../Snap.Hutao/ViewModel/WelcomeViewModel.cs | 12 ++-- .../Web/Hutao/HomaLogUploadClient.cs | 2 +- 78 files changed, 381 insertions(+), 321 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Core/Abstraction/IMappingFrom.cs rename src/Snap.Hutao/Snap.Hutao/Core/{HutaoOptions.cs => RuntimeOptions.cs} (87%) create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Entity/Abstraction/IDbMappingForeignKeyFrom.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/SqliteTypeNames.cs diff --git a/src/Snap.Hutao/Snap.Hutao/App.xaml.cs b/src/Snap.Hutao/Snap.Hutao/App.xaml.cs index 01024e88..2910fed9 100644 --- a/src/Snap.Hutao/Snap.Hutao/App.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/App.xaml.cs @@ -74,7 +74,7 @@ public sealed partial class App : Application private void LogDiagnosticInformation() { - HutaoOptions hutaoOptions = serviceProvider.GetRequiredService(); + RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); logger.LogInformation("FamilyName: {name}", hutaoOptions.FamilyName); logger.LogInformation("Version: {version}", hutaoOptions.Version); diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs b/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs index c9828b7f..82b0bbb1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs @@ -26,7 +26,7 @@ namespace Snap.Hutao.Control.Image; internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Control { private static readonly DependencyProperty SourceProperty = Property.Depend(nameof(Source), default(Uri), OnSourceChanged); - private static readonly ConcurrentCancellationTokenSource LoadingTokenSource = new(); + private readonly ConcurrentCancellationTokenSource loadingTokenSource = new(); private readonly IServiceProvider serviceProvider; @@ -92,7 +92,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co private static void OnSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs arg) { CompositionImage image = (CompositionImage)sender; - CancellationToken token = LoadingTokenSource.Register(image); + CancellationToken token = image.loadingTokenSource.Register(); IServiceProvider serviceProvider = image.serviceProvider; ILogger logger = serviceProvider.GetRequiredService>(); diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/IMappingFrom.cs b/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/IMappingFrom.cs new file mode 100644 index 00000000..e17b9c92 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/IMappingFrom.cs @@ -0,0 +1,20 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using System.Diagnostics.Contracts; + +namespace Snap.Hutao.Core.Abstraction; + +internal interface IMappingFrom + where TSelf : IMappingFrom +{ + [Pure] + static abstract TSelf From(TFrom source); +} + +internal interface IMappingFrom + where TSelf : IMappingFrom +{ + [Pure] + static abstract TSelf From(T1 t1, T2 t2); +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs index e418d9fb..ea0ecc7c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs @@ -221,7 +221,7 @@ internal sealed class ImageCache : IImageCache, IImageCacheFilePathOperation return cacheFolder!; } - baseFolder ??= serviceProvider.GetRequiredService().LocalCache; + baseFolder ??= serviceProvider.GetRequiredService().LocalCache; DirectoryInfo info = Directory.CreateDirectory(Path.Combine(baseFolder, CacheFolderName)); cacheFolder = info.FullName; diff --git a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocConfiguration.cs index 58053ae3..6c111994 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocConfiguration.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocConfiguration.cs @@ -37,7 +37,7 @@ internal static class IocConfiguration private static void AddDbContextCore(IServiceProvider provider, DbContextOptionsBuilder builder) { - HutaoOptions hutaoOptions = provider.GetRequiredService(); + RuntimeOptions hutaoOptions = provider.GetRequiredService(); string dbFile = System.IO.Path.Combine(hutaoOptions.DataFolder, "Userdata.db"); string sqlConnectionString = $"Data Source={dbFile}"; diff --git a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocHttpClientConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocHttpClientConfiguration.cs index ced883e7..b5876a2d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocHttpClientConfiguration.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocHttpClientConfiguration.cs @@ -29,7 +29,7 @@ internal static partial class IocHttpClientConfiguration /// 配置后的客户端 private static void DefaultConfiguration(IServiceProvider serviceProvider, HttpClient client) { - HutaoOptions hutaoOptions = serviceProvider.GetRequiredService(); + RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); client.Timeout = Timeout.InfiniteTimeSpan; client.DefaultRequestHeaders.UserAgent.ParseAdd(hutaoOptions.UserAgent); diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppInstanceExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppInstanceExtension.cs index ecb36125..03b0590f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppInstanceExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppInstanceExtension.cs @@ -40,6 +40,8 @@ internal static class AppInstanceExtension ReadOnlySpan handles = new(redirectEventHandle); CoWaitForMultipleObjects((uint)CWMO_FLAGS.CWMO_DEFAULT, INFINITE, handles, out uint _); + + // TODO: Release handle } private static void RunAction(object? state) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/HutaoOptions.cs b/src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptions.cs similarity index 87% rename from src/Snap.Hutao/Snap.Hutao/Core/HutaoOptions.cs rename to src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptions.cs index 7138c20b..6322a95c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/HutaoOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptions.cs @@ -8,30 +8,31 @@ using Snap.Hutao.Core.Setting; using System.IO; using System.Security.Principal; using Windows.ApplicationModel; +using Windows.Foundation.Metadata; using Windows.Storage; namespace Snap.Hutao.Core; /// -/// 胡桃选项 /// 存储环境相关的选项 /// 运行时运算得到的选项,无数据库交互 /// [Injection(InjectAs.Singleton)] -internal sealed class HutaoOptions : IOptions +internal sealed class RuntimeOptions : IOptions { - private readonly ILogger logger; + private readonly ILogger logger; private readonly bool isWebView2Supported; private readonly string webView2Version = SH.CoreWebView2HelperVersionUndetected; private bool? isElevated; + private bool? isWindows11; /// /// 构造一个新的胡桃选项 /// /// 日志器 - public HutaoOptions(ILogger logger) + public RuntimeOptions(ILogger logger) { this.logger = logger; @@ -97,8 +98,14 @@ internal sealed class HutaoOptions : IOptions /// public bool IsElevated { get => isElevated ??= GetElevated(); } + /// + /// 系统版本是否大于等于 Windows 11 + /// %programfiles(x86)%\Windows Kits\10\Platforms\UAP\10.0.22000.0\PreviousPlatforms.xml + /// + public bool Windows11OrHigher { get => isWindows11 ?? ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 14); } + /// - public HutaoOptions Value { get => this; } + public RuntimeOptions Value { get => this; } private static string GetDataFolderPath() { diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Setting/FeatureOptions.cs b/src/Snap.Hutao/Snap.Hutao/Core/Setting/FeatureOptions.cs index 41e2c438..7039ecb2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Setting/FeatureOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Setting/FeatureOptions.cs @@ -13,12 +13,14 @@ internal sealed class FeatureOptions : IReadOnlyCollection /// /// 启用实时便笺无感验证 /// - public Feature IsDailyNoteSilentVerificationEnabled { get; } = new("IsDailyNoteSilentVerificationEnabled", "启用实时便笺无感验证", "IsDailyNoteSilentVerificationEnabled", true); + public Feature IsDailyNoteSilentVerificationEnabled { get; } = new( + "IsDailyNoteSilentVerificationEnabled", "启用实时便笺无感验证", "IsDailyNoteSilentVerificationEnabled", true); /// /// 元数据检查是否忽略 /// - public Feature IsMetadataUpdateCheckSuppressed { get; } = new("IsMetadataUpdateCheckSuppressed", "禁用元数据更新检查", "IsMetadataUpdateCheckSuppressed", false); + public Feature IsMetadataUpdateCheckSuppressed { get; } = new( + "IsMetadataUpdateCheckSuppressed", "禁用元数据更新检查", "IsMetadataUpdateCheckSuppressed", false); /// public int Count { get => 2; } diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs b/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs index 6b27d46d..ba4f6c04 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs @@ -49,35 +49,4 @@ internal static class SettingKeys /// 1.7.0 版本指引状态 /// public const string Major1Minor7Revision0GuideState = "Major1Minor7Revision0GuideState"; - - #region StaticResource - - /// - /// 静态资源合约 - /// 新增合约时 请注意 - /// - /// 与 - /// - public const string StaticResourceV1Contract = "StaticResourceV1Contract"; - - /// - /// 静态资源合约V2 成就图标与物品图标 - /// - public const string StaticResourceV2Contract = "StaticResourceV2Contract"; - - /// - /// 静态资源合约V3 刷新 Skill Talent - /// - public const string StaticResourceV3Contract = "StaticResourceV3Contract"; - - /// - /// 静态资源合约V4 刷新 AvatarIcon - /// - public const string StaticResourceV4Contract = "StaticResourceV4Contract"; - - /// - /// 静态资源合约V5 刷新 AvatarIcon - /// - public const string StaticResourceV5Contract = "StaticResourceV5Contract"; - #endregion } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Setting/StaticResource.cs b/src/Snap.Hutao/Snap.Hutao/Core/Setting/StaticResource.cs index ca13939e..b94ebb6b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Setting/StaticResource.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Setting/StaticResource.cs @@ -9,6 +9,31 @@ namespace Snap.Hutao.Core.Setting; [HighQuality] internal static class StaticResource { + /// + /// 静态资源合约 + /// + public const string V1Contract = "StaticResourceV1Contract"; + + /// + /// 静态资源合约V2 成就图标与物品图标 + /// + public const string V2Contract = "StaticResourceV2Contract"; + + /// + /// 静态资源合约V3 刷新 Skill Talent + /// + public const string V3Contract = "StaticResourceV3Contract"; + + /// + /// 静态资源合约V4 刷新 AvatarIcon + /// + public const string V4Contract = "StaticResourceV4Contract"; + + /// + /// 静态资源合约V5 刷新 AvatarIcon + /// + public const string V5Contract = "StaticResourceV5Contract"; + /// /// 完成所有合约 /// @@ -41,18 +66,19 @@ internal static class StaticResource /// 静态资源合约尚未完成 public static bool IsAnyUnfulfilledContractPresent() { - return !LocalSetting.Get(SettingKeys.StaticResourceV1Contract, false) - || (!LocalSetting.Get(SettingKeys.StaticResourceV2Contract, false)) - || (!LocalSetting.Get(SettingKeys.StaticResourceV3Contract, false)) - || (!LocalSetting.Get(SettingKeys.StaticResourceV4Contract, false)); + return !LocalSetting.Get(V1Contract, false) + || (!LocalSetting.Get(V2Contract, false)) + || (!LocalSetting.Get(V3Contract, false)) + || (!LocalSetting.Get(V4Contract, false)) + || (!LocalSetting.Get(V5Contract, false)); } private static void SetContractsState(bool state) { - LocalSetting.Set(SettingKeys.StaticResourceV1Contract, state); - LocalSetting.Set(SettingKeys.StaticResourceV2Contract, state); - LocalSetting.Set(SettingKeys.StaticResourceV3Contract, state); - LocalSetting.Set(SettingKeys.StaticResourceV4Contract, state); - LocalSetting.Set(SettingKeys.StaticResourceV5Contract, state); + LocalSetting.Set(V1Contract, state); + LocalSetting.Set(V2Contract, state); + LocalSetting.Set(V3Contract, state); + LocalSetting.Set(V4Contract, state); + LocalSetting.Set(V5Contract, state); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Threading/ConcurrentCancellationTokenSource.cs b/src/Snap.Hutao/Snap.Hutao/Core/Threading/ConcurrentCancellationTokenSource.cs index 78059b0e..b3f865a2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Threading/ConcurrentCancellationTokenSource.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Threading/ConcurrentCancellationTokenSource.cs @@ -1,8 +1,6 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using System.Collections.Concurrent; - namespace Snap.Hutao.Core.Threading; /// @@ -24,31 +22,4 @@ internal class ConcurrentCancellationTokenSource source = new(); return source.Token; } -} - -/// -/// 有区分项的并发 -/// -/// 项类型 -[HighQuality] -[SuppressMessage("", "SA1402")] -internal class ConcurrentCancellationTokenSource - where TItem : notnull -{ - private readonly ConcurrentDictionary waitingItems = new(); - - /// - /// 为某个项注册取消令牌 - /// - /// 区分项 - /// 取消令牌 - public CancellationToken Register(TItem item) - { - if (waitingItems.TryRemove(item, out CancellationTokenSource? previousSource)) - { - previousSource.Cancel(); - } - - return waitingItems.GetOrAdd(item, new CancellationTokenSource()).Token; - } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Threading/SemaphoreSlimToken.cs b/src/Snap.Hutao/Snap.Hutao/Core/Threading/SemaphoreSlimToken.cs index d371c4b9..6d159cbb 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Threading/SemaphoreSlimToken.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Threading/SemaphoreSlimToken.cs @@ -1,6 +1,8 @@ -namespace Snap.Hutao.Core.Threading; +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Core.Threading; -[SuppressMessage("", "SA1201")] internal readonly struct SemaphoreSlimToken : IDisposable { private readonly SemaphoreSlim semaphoreSlim; diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Threading/TaskContext.cs b/src/Snap.Hutao/Snap.Hutao/Core/Threading/TaskContext.cs index aa65daab..5ae43f2c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Threading/TaskContext.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Threading/TaskContext.cs @@ -38,7 +38,7 @@ internal sealed class TaskContext : ITaskContext /// public void InvokeOnMainThread(Action action) { - if (dispatcherQueue!.HasThreadAccess) + if (dispatcherQueue.HasThreadAccess) { action(); } diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Threading/TaskExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/Threading/TaskExtension.cs index 68b57c6e..dc2af2bf 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Threading/TaskExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Threading/TaskExtension.cs @@ -1,6 +1,8 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.ExceptionService; + namespace Snap.Hutao.Core.Threading; /// @@ -30,7 +32,7 @@ internal static class TaskExtension { if (System.Diagnostics.Debugger.IsAttached) { - _ = ex; + System.Diagnostics.Debug.WriteLine(ExceptionFormat.Format(ex)); System.Diagnostics.Debugger.Break(); } } @@ -58,7 +60,7 @@ internal static class TaskExtension } catch (Exception e) { - logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), e.GetBaseException()); + logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException())); } } @@ -80,7 +82,7 @@ internal static class TaskExtension } catch (Exception e) { - logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), e.GetBaseException()); + logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException())); onException?.Invoke(e); } } @@ -104,7 +106,7 @@ internal static class TaskExtension } catch (Exception e) { - logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), e.GetBaseException()); + logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException())); onException?.Invoke(e); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Validation/Must.cs b/src/Snap.Hutao/Snap.Hutao/Core/Validation/Must.cs index acc8021a..07023865 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Validation/Must.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Validation/Must.cs @@ -52,19 +52,4 @@ internal static class Must { throw new NotSupportedException(context); } - - /// - /// Throws an if the specified parameter's value is null. - /// - /// The type of the parameter. - /// The value of the argument. - /// The name of the parameter to include in any thrown exception. - /// The value of the parameter. - /// Thrown if is null. - [MethodImpl(MethodImplOptions.NoInlining)] - public static T NotNull([NotNull] T value, [CallerArgumentExpression(nameof(value))] string? parameterName = null) - where T : class // ensures value-types aren't passed to a null checking method - { - return value ?? throw new ArgumentNullException(parameterName); - } } diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs index 173214c3..0ec57711 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs @@ -60,7 +60,7 @@ internal sealed class ExtendedWindow : IRecipient(); + RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); WindowOptions options = window.WindowOptions; window.AppWindow.Title = string.Format(SH.AppNameAndVersion, hutaoOptions.Version); @@ -73,7 +73,7 @@ internal sealed class ExtendedWindow : IRecipient(); UpdateSystemBackdrop(appOptions.BackdropType); @@ -182,7 +182,7 @@ internal sealed class ExtendedWindow : IRecipient - /// 获取窗体当前的DPI缩放比 - /// - /// 窗体句柄 - /// 缩放比 - public static double GetScaleForWindowHandle(in HWND hwnd) - { - uint dpi = GetDpiForWindow(hwnd); - return Math.Round(dpi / 96D, 2, MidpointRounding.AwayFromZero); - } - - /// - /// 将窗口设为前台窗口 - /// - /// 窗口句柄 - public static unsafe void BringToForeground(in HWND hwnd) - { - HWND fgHwnd = GetForegroundWindow(); - - uint threadIdHwnd = GetWindowThreadProcessId(hwnd); - uint threadIdFgHwnd = GetWindowThreadProcessId(fgHwnd); - - if (threadIdHwnd != threadIdFgHwnd) - { - AttachThreadInput(threadIdHwnd, threadIdFgHwnd, true); - SetForegroundWindow(hwnd); - AttachThreadInput(threadIdHwnd, threadIdFgHwnd, false); - } - else - { - SetForegroundWindow(hwnd); - } - } - private static void TransformToCenterScreen(ref RectInt32 rect) { DisplayArea displayArea = DisplayArea.GetFromRect(rect, DisplayAreaFallback.Primary); diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs index 784f7513..008a7b09 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs @@ -6,6 +6,7 @@ using Microsoft.UI.Xaml; using Windows.Graphics; using Windows.Win32.Foundation; using WinRT.Interop; +using static Windows.Win32.PInvoke; namespace Snap.Hutao.Core.Windowing; @@ -53,4 +54,37 @@ internal readonly struct WindowOptions InitSize = initSize; PersistSize = persistSize; } + + /// + /// 获取窗体当前的DPI缩放比 + /// + /// 缩放比 + public double GetWindowScale() + { + uint dpi = GetDpiForWindow(Hwnd); + return Math.Round(dpi / 96D, 2, MidpointRounding.AwayFromZero); + } + + /// + /// 将窗口设为前台窗口 + /// + /// 窗口句柄 + public unsafe void BringToForeground() + { + HWND fgHwnd = GetForegroundWindow(); + + uint threadIdHwnd = GetWindowThreadProcessId(Hwnd); + uint threadIdFgHwnd = GetWindowThreadProcessId(fgHwnd); + + if (threadIdHwnd != threadIdFgHwnd) + { + AttachThreadInput(threadIdHwnd, threadIdFgHwnd, true); + SetForegroundWindow(Hwnd); + AttachThreadInput(threadIdHwnd, threadIdFgHwnd, false); + } + else + { + SetForegroundWindow(Hwnd); + } + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowSubclass.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowSubclass.cs index 7c2da538..a24a8d98 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowSubclass.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowSubclass.cs @@ -93,7 +93,8 @@ internal sealed class WindowSubclass : IDisposable { case WM_GETMINMAXINFO: { - double scalingFactor = Persistence.GetScaleForWindowHandle(hwnd); + uint dpi = GetDpiForWindow(hwnd); + double scalingFactor = Math.Round(dpi / 96D, 2, MidpointRounding.AwayFromZero); window.ProcessMinMaxInfo((MINMAXINFO*)lParam.Value, scalingFactor); break; } diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.Dictionary.cs b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.Dictionary.cs index 419bc009..8ac26d86 100644 --- a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.Dictionary.cs +++ b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.Dictionary.cs @@ -66,7 +66,7 @@ internal static partial class EnumerableExtension } /// - public static Dictionary ToDictionaryOverride(this IEnumerable source, Func keySelector) + public static Dictionary ToDictionaryIgnoringDuplicateKeys(this IEnumerable source, Func keySelector) where TKey : notnull { Dictionary dictionary = new(); @@ -80,14 +80,14 @@ internal static partial class EnumerableExtension } /// - public static Dictionary ToDictionaryOverride(this IEnumerable source, Func keySelector, Func valueSelector) + public static Dictionary ToDictionaryIgnoringDuplicateKeys(this IEnumerable source, Func keySelector, Func elementSelector) where TKey : notnull { Dictionary dictionary = new(); foreach (TSource value in source) { - dictionary[keySelector(value)] = valueSelector(value); + dictionary[keySelector(value)] = elementSelector(value); } return dictionary; diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs index b2246dbe..f4b10ce2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs @@ -31,6 +31,7 @@ internal static partial class EnumerableExtension /// 源的类型 /// 源 /// 集合 + [Obsolete("Use C# 12 Collection Literal instead")] public static IEnumerable Enumerate(this TSource source) { yield return source; diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/ObjectExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/ObjectExtension.cs index fc530196..977bb949 100644 --- a/src/Snap.Hutao/Snap.Hutao/Extension/ObjectExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Extension/ObjectExtension.cs @@ -16,13 +16,12 @@ internal static class ObjectExtension /// 数据类型 /// 源 /// 数组 - [Obsolete("Use C# 12 Collection Literals")] + [Obsolete("Use C# 12 Collection Literals when we migrate")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T[] ToArray(this T source) { // TODO: use C# 12 collection literals // [ source ] - // and mark this as Obsolete return new[] { source }; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/Abstraction/IContentDialogFactory.cs b/src/Snap.Hutao/Snap.Hutao/Factory/Abstraction/IContentDialogFactory.cs index 469136dd..1794360a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Factory/Abstraction/IContentDialogFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Factory/Abstraction/IContentDialogFactory.cs @@ -17,7 +17,7 @@ internal interface IContentDialogFactory /// 标题 /// 内容 /// 结果 - ValueTask ConfirmAsync(string title, string content); + ValueTask CreateForConfirmAsync(string title, string content); /// /// 异步确认或取消 @@ -26,7 +26,7 @@ internal interface IContentDialogFactory /// 内容 /// 默认按钮 /// 结果 - ValueTask ConfirmCancelAsync(string title, string content, ContentDialogButton defaultButton = ContentDialogButton.Close); + ValueTask CreateForConfirmCancelAsync(string title, string content, ContentDialogButton defaultButton = ContentDialogButton.Close); /// /// 异步创建一个新的内容对话框,用于提示未知的进度 diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialogFactory.cs b/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialogFactory.cs index 935fef52..d89d5359 100644 --- a/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialogFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialogFactory.cs @@ -26,18 +26,35 @@ internal sealed class ContentDialogFactory : IContentDialogFactory } /// - public async ValueTask ConfirmAsync(string title, string content) + public async ValueTask CreateForConfirmAsync(string title, string content) { - ContentDialog dialog = await CreateForConfirmAsync(title, content).ConfigureAwait(false); await taskContext.SwitchToMainThreadAsync(); + ContentDialog dialog = new() + { + XamlRoot = mainWindow.Content.XamlRoot, + Title = title, + Content = content, + DefaultButton = ContentDialogButton.Primary, + PrimaryButtonText = SH.ContentDialogConfirmPrimaryButtonText, + }; + return await dialog.ShowAsync(); } /// - public async ValueTask ConfirmCancelAsync(string title, string content, ContentDialogButton defaultButton = ContentDialogButton.Close) + public async ValueTask CreateForConfirmCancelAsync(string title, string content, ContentDialogButton defaultButton = ContentDialogButton.Close) { - ContentDialog dialog = await CreateForConfirmCancelAsync(title, content, defaultButton).ConfigureAwait(false); await taskContext.SwitchToMainThreadAsync(); + ContentDialog dialog = new() + { + XamlRoot = mainWindow.Content.XamlRoot, + Title = title, + Content = content, + DefaultButton = defaultButton, + PrimaryButtonText = SH.ContentDialogConfirmPrimaryButtonText, + CloseButtonText = SH.ContentDialogCancelCloseButtonText, + }; + return await dialog.ShowAsync(); } @@ -54,35 +71,4 @@ internal sealed class ContentDialogFactory : IContentDialogFactory return dialog; } - - private async ValueTask CreateForConfirmAsync(string title, string content) - { - await taskContext.SwitchToMainThreadAsync(); - ContentDialog dialog = new() - { - XamlRoot = mainWindow.Content.XamlRoot, - Title = title, - Content = content, - DefaultButton = ContentDialogButton.Primary, - PrimaryButtonText = SH.ContentDialogConfirmPrimaryButtonText, - }; - - return dialog; - } - - private async ValueTask CreateForConfirmCancelAsync(string title, string content, ContentDialogButton defaultButton = ContentDialogButton.Close) - { - await taskContext.SwitchToMainThreadAsync(); - ContentDialog dialog = new() - { - XamlRoot = mainWindow.Content.XamlRoot, - Title = title, - Content = content, - DefaultButton = defaultButton, - PrimaryButtonText = SH.ContentDialogConfirmPrimaryButtonText, - CloseButtonText = SH.ContentDialogCancelCloseButtonText, - }; - - return dialog; - } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/PickerFactory.cs b/src/Snap.Hutao/Snap.Hutao/Factory/PickerFactory.cs index 61c92c51..4024037b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Factory/PickerFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Factory/PickerFactory.cs @@ -1,8 +1,8 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core; using Snap.Hutao.Factory.Abstraction; -using Windows.Foundation.Metadata; using Windows.Storage.Pickers; using WinRT.Interop; @@ -10,21 +10,14 @@ namespace Snap.Hutao.Factory; /// [HighQuality] +[ConstructorGenerated] [Injection(InjectAs.Transient, typeof(IPickerFactory))] -internal class PickerFactory : IPickerFactory +internal sealed partial class PickerFactory : IPickerFactory { private const string AnyType = "*"; private readonly MainWindow mainWindow; - - /// - /// 构造一个新的文件选择器工厂 - /// - /// 主窗体的引用注入 - public PickerFactory(MainWindow mainWindow) - { - this.mainWindow = mainWindow; - } + private readonly RuntimeOptions runtimeOptions; /// public FileOpenPicker GetFileOpenPicker(PickerLocationId location, string commitButton, params string[] fileTypes) @@ -40,7 +33,7 @@ internal class PickerFactory : IPickerFactory } // below Windows 11 - if (!ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 13)) + if (!runtimeOptions.Windows11OrHigher) { // https://github.com/microsoft/WindowsAppSDK/issues/2931 picker.FileTypeFilter.Add(AnyType); @@ -72,7 +65,7 @@ internal class PickerFactory : IPickerFactory FolderPicker picker = GetInitializedPicker(); // below Windows 11 - if (!ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 13)) + if (!runtimeOptions.Windows11OrHigher) { // https://github.com/microsoft/WindowsAppSDK/issues/2931 picker.FileTypeFilter.Add(AnyType); diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableAvatar.cs b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableAvatar.cs index cc44896c..38c4b6aa 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableAvatar.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableAvatar.cs @@ -2,7 +2,9 @@ // Licensed under the MIT license. using CommunityToolkit.Mvvm.ComponentModel; +using Snap.Hutao.Core.Abstraction; using Snap.Hutao.Model.Intrinsic; +using Snap.Hutao.Model.Metadata.Avatar; using Snap.Hutao.Model.Metadata.Converter; using Snap.Hutao.Model.Primitive; using Snap.Hutao.ViewModel.AvatarProperty; @@ -13,7 +15,11 @@ namespace Snap.Hutao.Model.Calculable; /// 可计算角色 /// [HighQuality] -internal sealed class CalculableAvatar : ObservableObject, ICalculableAvatar +internal sealed class CalculableAvatar + : ObservableObject, + ICalculableAvatar, + IMappingFrom, + IMappingFrom { private uint levelCurrent; private uint levelTarget; @@ -22,7 +28,7 @@ internal sealed class CalculableAvatar : ObservableObject, ICalculableAvatar /// 构造一个新的可计算角色 /// /// 角色 - public CalculableAvatar(Metadata.Avatar.Avatar avatar) + private CalculableAvatar(Avatar avatar) { AvatarId = avatar.Id; LevelMin = 1; @@ -40,7 +46,7 @@ internal sealed class CalculableAvatar : ObservableObject, ICalculableAvatar /// 构造一个新的可计算角色 /// /// 角色 - public CalculableAvatar(AvatarView avatar) + private CalculableAvatar(AvatarView avatar) { AvatarId = avatar.Id; LevelMin = avatar.LevelNumber; @@ -80,4 +86,14 @@ internal sealed class CalculableAvatar : ObservableObject, ICalculableAvatar /// public uint LevelTarget { get => levelTarget; set => SetProperty(ref levelTarget, value); } + + public static CalculableAvatar From(Avatar source) + { + return new(source); + } + + public static CalculableAvatar From(AvatarView source) + { + return new(source); + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableOptions.cs b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableOptions.cs index 01ef76df..4a8e54b9 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableOptions.cs @@ -6,8 +6,18 @@ namespace Snap.Hutao.Model.Calculable; /// /// 可计算物品选项 /// -internal sealed class CalculableOptions +internal readonly struct CalculableOptions { + /// + /// 角色 + /// + public readonly ICalculableAvatar? Avatar; + + /// + /// 武器 + /// + public readonly ICalculableWeapon? Weapon; + /// /// 构造一个新的可计算物品选项 /// @@ -18,14 +28,4 @@ internal sealed class CalculableOptions Avatar = avatar; Weapon = weapon; } - - /// - /// 角色 - /// - public ICalculableAvatar? Avatar { get; } - - /// - /// 武器 - /// - public ICalculableWeapon? Weapon { get; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableSkill.cs b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableSkill.cs index d3d253ad..7bdc9cca 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableSkill.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableSkill.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using CommunityToolkit.Mvvm.ComponentModel; +using Snap.Hutao.Core.Abstraction; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata.Avatar; using Snap.Hutao.Model.Metadata.Converter; @@ -14,7 +15,11 @@ namespace Snap.Hutao.Model.Calculable; /// 可计算的技能 /// [HighQuality] -internal sealed class CalculableSkill : ObservableObject, ICalculableSkill +internal sealed class CalculableSkill + : ObservableObject, + ICalculableSkill, + IMappingFrom, + IMappingFrom { private uint levelCurrent; private uint levelTarget; @@ -23,7 +28,7 @@ internal sealed class CalculableSkill : ObservableObject, ICalculableSkill /// 构造一个新的可计算的技能 /// /// 技能 - public CalculableSkill(ProudableSkill skill) + private CalculableSkill(ProudableSkill skill) { GroupId = skill.GroupId; LevelMin = 1; @@ -40,7 +45,7 @@ internal sealed class CalculableSkill : ObservableObject, ICalculableSkill /// 构造一个新的可计算的技能 /// /// 技能 - public CalculableSkill(SkillView skill) + private CalculableSkill(SkillView skill) { GroupId = skill.GroupId; LevelMin = skill.LevelNumber; @@ -76,4 +81,14 @@ internal sealed class CalculableSkill : ObservableObject, ICalculableSkill /// public uint LevelTarget { get => levelTarget; set => SetProperty(ref levelTarget, value); } + + public static CalculableSkill From(ProudableSkill source) + { + return new(source); + } + + public static CalculableSkill From(SkillView source) + { + return new(source); + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableWeapon.cs b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableWeapon.cs index aef8eda9..96c8a808 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableWeapon.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Calculable/CalculableWeapon.cs @@ -2,8 +2,10 @@ // Licensed under the MIT license. using CommunityToolkit.Mvvm.ComponentModel; +using Snap.Hutao.Core.Abstraction; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata.Converter; +using Snap.Hutao.Model.Metadata.Weapon; using Snap.Hutao.Model.Primitive; using Snap.Hutao.ViewModel.AvatarProperty; @@ -13,7 +15,11 @@ namespace Snap.Hutao.Model.Calculable; /// 可计算武器 /// [HighQuality] -internal class CalculableWeapon : ObservableObject, ICalculableWeapon +internal sealed class CalculableWeapon + : ObservableObject, + ICalculableWeapon, + IMappingFrom, + IMappingFrom { private uint levelCurrent; private uint levelTarget; @@ -22,7 +28,7 @@ internal class CalculableWeapon : ObservableObject, ICalculableWeapon /// 构造一个新的可计算武器 /// /// 武器 - public CalculableWeapon(Metadata.Weapon.Weapon weapon) + private CalculableWeapon(Weapon weapon) { WeaponId = weapon.Id; LevelMin = 1; @@ -39,7 +45,7 @@ internal class CalculableWeapon : ObservableObject, ICalculableWeapon /// 构造一个新的可计算武器 /// /// 武器 - public CalculableWeapon(WeaponView weapon) + private CalculableWeapon(WeaponView weapon) { WeaponId = weapon.Id; LevelMin = weapon.LevelNumber; @@ -75,4 +81,14 @@ internal class CalculableWeapon : ObservableObject, ICalculableWeapon /// public uint LevelTarget { get => levelTarget; set => SetProperty(ref levelTarget, value); } + + public static CalculableWeapon From(Weapon source) + { + return new(source); + } + + public static CalculableWeapon From(WeaponView source) + { + return new(source); + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Abstraction/IDbMappingForeignKeyFrom.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Abstraction/IDbMappingForeignKeyFrom.cs new file mode 100644 index 00000000..68d89754 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Abstraction/IDbMappingForeignKeyFrom.cs @@ -0,0 +1,18 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using System.Diagnostics.Contracts; + +namespace Snap.Hutao.Model.Entity.Abstraction; + +internal interface IDbMappingForeignKeyFrom +{ + [Pure] + static abstract TSource From(in Guid foreignKey, in TFrom from); +} + +internal interface IDbMappingForeignKeyFrom +{ + [Pure] + static abstract TSource From(in Guid foreignKey, in T1 param1, in T2 param2); +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Achievement.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Achievement.cs index cb2d4dfb..35275823 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Achievement.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Achievement.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Model.Entity.Abstraction; using Snap.Hutao.Model.InterChange.Achievement; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Primitive; @@ -14,7 +15,11 @@ namespace Snap.Hutao.Model.Entity; /// [HighQuality] [Table("achievements")] -internal sealed class Achievement : IEquatable +[SuppressMessage("", "SA1124")] +internal sealed class Achievement + : IEquatable, + IDbMappingForeignKeyFrom, + IDbMappingForeignKeyFrom { /// /// 内部Id @@ -57,14 +62,14 @@ internal sealed class Achievement : IEquatable /// /// 创建一个新的成就 /// - /// 对应的用户id + /// 对应的用户id /// 成就Id /// 新创建的成就 - public static Achievement Create(in Guid userId, in AchievementId id) + public static Achievement From(in Guid archiveId, in AchievementId id) { return new() { - ArchiveId = userId, + ArchiveId = archiveId, Id = id, Current = 0, Time = DateTimeOffset.MinValue, @@ -77,7 +82,7 @@ internal sealed class Achievement : IEquatable /// 对应的用户id /// uiaf项 /// 新创建的成就 - public static Achievement Create(in Guid userId, UIAFItem uiaf) + public static Achievement From(in Guid userId, in UIAFItem uiaf) { return new() { @@ -89,21 +94,6 @@ internal sealed class Achievement : IEquatable }; } - /// - /// 转换到UIAF物品 - /// - /// UIAF物品 - public UIAFItem ToUIAFItem() - { - return new() - { - Id = Id, - Current = Current, - Status = Status, - Timestamp = Time.ToUnixTimeSeconds(), - }; - } - /// public bool Equals(Achievement? other) { @@ -121,6 +111,8 @@ internal sealed class Achievement : IEquatable } } + #region Object + /// public override bool Equals(object? obj) { @@ -132,4 +124,5 @@ internal sealed class Achievement : IEquatable { return HashCode.Combine(ArchiveId, Id, Current, Status, Time); } + #endregion } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/AchievementArchive.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/AchievementArchive.cs index b1a4fd7c..d11059f7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/AchievementArchive.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/AchievementArchive.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.Abstraction; using Snap.Hutao.Core.Database; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -11,7 +12,7 @@ namespace Snap.Hutao.Model.Entity; /// 成就存档 /// [Table("achievement_archives")] -internal sealed class AchievementArchive : ISelectable +internal sealed class AchievementArchive : ISelectable, IMappingFrom { /// /// 内部Id @@ -35,7 +36,7 @@ internal sealed class AchievementArchive : ISelectable /// /// 名称 /// 新存档 - public static AchievementArchive Create(string name) + public static AchievementArchive From(string name) { return new() { Name = name }; } diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/AvatarInfo.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/AvatarInfo.cs index 2a549d31..9d1ecbd0 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/AvatarInfo.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/AvatarInfo.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.Abstraction; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -11,10 +12,10 @@ namespace Snap.Hutao.Model.Entity; /// [HighQuality] [Table("avatar_infos")] -internal sealed class AvatarInfo +internal sealed class AvatarInfo : IMappingFrom { /// - /// 内部Id + /// 内部 Id /// [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] @@ -36,7 +37,7 @@ internal sealed class AvatarInfo /// uid /// 角色信息 /// 实体角色信息 - public static AvatarInfo Create(string uid, Web.Enka.Model.AvatarInfo info) + public static AvatarInfo From(string uid, Web.Enka.Model.AvatarInfo info) { return new() { Uid = uid, Info = info }; } diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/AvatarInfoConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/AvatarInfoConfiguration.cs index 866001ac..f2cbfbc1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/AvatarInfoConfiguration.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/AvatarInfoConfiguration.cs @@ -16,7 +16,7 @@ internal sealed class AvatarInfoConfiguration : IEntityTypeConfiguration builder) { builder.Property(e => e.Info) - .HasColumnType("TEXT") + .HasColumnType(SqliteTypeNames.Text) .HasConversion>(); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/DailyNoteEntryConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/DailyNoteEntryConfiguration.cs index 87d17931..f9bb9780 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/DailyNoteEntryConfiguration.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/DailyNoteEntryConfiguration.cs @@ -16,7 +16,7 @@ internal sealed class DailyNoteEntryConfiguration : IEntityTypeConfiguration builder) { builder.Property(e => e.DailyNote) - .HasColumnType("TEXT") + .HasColumnType(SqliteTypeNames.Text) .HasConversion>(); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/InventoryReliquaryConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/InventoryReliquaryConfiguration.cs index 7d1b09e9..0b5891b9 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/InventoryReliquaryConfiguration.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/InventoryReliquaryConfiguration.cs @@ -16,7 +16,7 @@ internal sealed class InventoryReliquaryConfiguration : IEntityTypeConfiguration public void Configure(EntityTypeBuilder builder) { builder.Property(e => e.AppendPropIdList) - .HasColumnType("TEXT") + .HasColumnType(SqliteTypeNames.Text) .HasConversion( list => list.ToString(','), text => text.Split(',', StringSplitOptions.None).Select(int.Parse).ToList()); diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/SpiralAbyssEntryConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/SpiralAbyssEntryConfiguration.cs index 2924e25e..0f0f3d77 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/SpiralAbyssEntryConfiguration.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/SpiralAbyssEntryConfiguration.cs @@ -16,7 +16,7 @@ internal sealed class SpiralAbyssEntryConfiguration : IEntityTypeConfiguration builder) { builder.Property(e => e.SpiralAbyss) - .HasColumnType("TEXT") + .HasColumnType(SqliteTypeNames.Text) .HasConversion>(); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/SqliteTypeNames.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/SqliteTypeNames.cs new file mode 100644 index 00000000..5255dea5 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/SqliteTypeNames.cs @@ -0,0 +1,12 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Model.Entity.Configuration; + +internal sealed class SqliteTypeNames +{ + public const string Integer = "INTEGER"; + public const string Real = "REAL"; + public const string Blob = "BLOB"; + public const string Text = "TEXT"; +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/UserConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/UserConfiguration.cs index 8777baaf..e62357c9 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/UserConfiguration.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/UserConfiguration.cs @@ -17,15 +17,15 @@ internal sealed class UserConfiguration : IEntityTypeConfiguration public void Configure(EntityTypeBuilder builder) { builder.Property(e => e.CookieToken) - .HasColumnType("TEXT") + .HasColumnType(SqliteTypeNames.Text) .HasConversion(e => e!.ToString(), e => Cookie.Parse(e)); builder.Property(e => e.LToken) - .HasColumnType("TEXT") + .HasColumnType(SqliteTypeNames.Text) .HasConversion(e => e!.ToString(), e => Cookie.Parse(e)); builder.Property(e => e.SToken) - .HasColumnType("TEXT") + .HasColumnType(SqliteTypeNames.Text) .HasConversion(e => e!.ToString(), e => Cookie.Parse(e)); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateEntry.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateEntry.cs index e986bf09..cd892254 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateEntry.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateEntry.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Model.Entity.Abstraction; using Snap.Hutao.Model.Entity.Primitive; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -12,7 +13,7 @@ namespace Snap.Hutao.Model.Entity; /// [HighQuality] [Table("cultivate_entries")] -internal sealed class CultivateEntry +internal sealed class CultivateEntry : IDbMappingForeignKeyFrom { /// /// 内部Id @@ -49,7 +50,7 @@ internal sealed class CultivateEntry /// 类型 /// 主Id /// 养成入口点 - public static CultivateEntry Create(in Guid projectId, CultivateType type, uint id) + public static CultivateEntry From(in Guid projectId, in CultivateType type, in uint id) { return new() { diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateItem.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateItem.cs index aff1d82d..af0ffec5 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateItem.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateItem.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Model.Entity.Abstraction; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -11,7 +12,7 @@ namespace Snap.Hutao.Model.Entity; /// [HighQuality] [Table("cultivate_items")] -internal sealed class CultivateItem +internal sealed class CultivateItem : IDbMappingForeignKeyFrom { /// /// 内部Id @@ -50,16 +51,15 @@ internal sealed class CultivateItem /// 创建一个新的养成物品 /// /// 入口点 Id - /// 物品 Id - /// 个数 + /// 物品 /// 养成物品 - public static CultivateItem Create(in Guid entryId, int itemId, int count) + public static CultivateItem From(in Guid entryId, in Web.Hoyolab.Takumi.Event.Calculate.Item item) { return new() { EntryId = entryId, - ItemId = itemId, - Count = count, + ItemId = item.Id, + Count = item.Num, }; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateProject.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateProject.cs index 9405805c..d9cef50d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateProject.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/CultivateProject.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.Abstraction; using Snap.Hutao.Core.Database; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -12,7 +13,7 @@ namespace Snap.Hutao.Model.Entity; /// [HighQuality] [Table("cultivate_projects")] -internal sealed class CultivateProject : ISelectable +internal sealed class CultivateProject : ISelectable, IMappingFrom { /// /// 内部Id @@ -42,7 +43,7 @@ internal sealed class CultivateProject : ISelectable /// 名称 /// 绑定的Uid /// 新的养成计划 - public static CultivateProject Create(string name, string? attachedUid = null) + public static CultivateProject From(string name, string? attachedUid = null) { return new() { Name = name, AttachedUid = attachedUid }; } diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/DailyNoteEntry.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/DailyNoteEntry.cs index 592a87d5..d3a3c6cf 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/DailyNoteEntry.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/DailyNoteEntry.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using CommunityToolkit.Mvvm.ComponentModel; +using Snap.Hutao.Core.Abstraction; using Snap.Hutao.ViewModel.User; using Snap.Hutao.Web.Hoyolab.Takumi.Binding; using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.DailyNote; @@ -15,7 +16,7 @@ namespace Snap.Hutao.Model.Entity; /// [HighQuality] [Table("daily_notes")] -internal sealed class DailyNoteEntry : ObservableObject +internal sealed class DailyNoteEntry : ObservableObject, IMappingFrom { /// /// 内部Id @@ -106,7 +107,7 @@ internal sealed class DailyNoteEntry : ObservableObject /// /// 用户与角色 /// 新的实时便笺 - public static DailyNoteEntry Create(UserAndUid userAndUid) + public static DailyNoteEntry From(UserAndUid userAndUid) { return new() { diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/GachaArchive.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/GachaArchive.cs index 9a3096ed..3de78cb3 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/GachaArchive.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/GachaArchive.cs @@ -3,6 +3,7 @@ using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; +using Snap.Hutao.Core.Abstraction; using Snap.Hutao.Core.Database; using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Service.GachaLog; @@ -17,7 +18,7 @@ namespace Snap.Hutao.Model.Entity; /// [HighQuality] [Table("gacha_archives")] -internal sealed class GachaArchive : ISelectable +internal sealed class GachaArchive : ISelectable, IMappingFrom { /// /// 内部Id @@ -39,7 +40,7 @@ internal sealed class GachaArchive : ISelectable /// /// uid /// 新的卡池存档 - public static GachaArchive Create(string uid) + public static GachaArchive From(string uid) { return new() { Uid = uid }; } @@ -69,7 +70,7 @@ internal sealed class GachaArchive : ISelectable if (archive == null) { - GachaArchive created = Create(context.Uid); + GachaArchive created = From(context.Uid); context.GachaArchives.AddAndSave(created); context.TaskContext.InvokeOnMainThread(() => context.ArchiveCollection.Add(created)); archive = created; 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 8ef870a3..73be152c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Achievement/UIAFInfo.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Achievement/UIAFInfo.cs @@ -51,7 +51,7 @@ internal sealed class UIAFInfo /// 专用 UIAF 信息 public static UIAFInfo Create(IServiceProvider serviceProvider) { - HutaoOptions hutaoOptions = serviceProvider.GetRequiredService(); + RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); return new() { diff --git a/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Achievement/UIAFItem.cs b/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Achievement/UIAFItem.cs index dacbcd45..acd14d89 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Achievement/UIAFItem.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Achievement/UIAFItem.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.Abstraction; using Snap.Hutao.Model.Intrinsic; namespace Snap.Hutao.Model.InterChange.Achievement; @@ -8,7 +9,7 @@ namespace Snap.Hutao.Model.InterChange.Achievement; /// /// UIAF 项 /// -internal sealed class UIAFItem +internal sealed class UIAFItem : IMappingFrom { /// /// 成就Id @@ -34,4 +35,15 @@ internal sealed class UIAFItem /// [JsonPropertyName("status")] public AchievementStatus Status { get; set; } + + public static UIAFItem From(Entity.Achievement source) + { + return new() + { + Id = source.Id, + Current = source.Current, + Status = source.Status, + Timestamp = source.Time.ToUnixTimeSeconds(), + }; + } } \ No newline at end of file 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 19a93699..0ddb58a6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/InterChange/GachaLog/UIGFInfo.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/InterChange/GachaLog/UIGFInfo.cs @@ -64,7 +64,7 @@ internal sealed class UIGFInfo /// 专用 UIGF 信息 public static UIGFInfo Create(IServiceProvider serviceProvider, string uid) { - HutaoOptions hutaoOptions = serviceProvider.GetRequiredService(); + RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); return new() { diff --git a/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Inventory/UIIFInfo.cs b/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Inventory/UIIFInfo.cs index 8e199745..81a4e6f4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Inventory/UIIFInfo.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/InterChange/Inventory/UIIFInfo.cs @@ -64,7 +64,7 @@ internal sealed class UIIFInfo /// 专用 UIGF 信息 public static UIIFInfo Create(IServiceProvider serviceProvider, string uid) { - HutaoOptions hutaoOptions = serviceProvider.GetRequiredService(); + RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); return new() { diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs index 73db31c0..4788d149 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs @@ -43,7 +43,7 @@ internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IName /// public ICalculableAvatar ToCalculable() { - return new CalculableAvatar(this); + return CalculableAvatar.From(this); } /// diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.Implementation.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.Implementation.cs index bf37e39d..1b64f8eb 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.Implementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.Implementation.cs @@ -13,6 +13,6 @@ internal sealed partial class ProudableSkill : ICalculableSource public ICalculableSkill ToCalculable() { - return new CalculableSkill(this); + return CalculableSkill.From(this); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs index 8558a149..579b329f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs @@ -36,7 +36,7 @@ internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource /// public ICalculableWeapon ToCalculable() { - return new CalculableWeapon(this); + return CalculableWeapon.From(this); } /// diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementDbBulkOperation.cs b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementDbBulkOperation.cs index 4cd626b3..30f92579 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementDbBulkOperation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementDbBulkOperation.cs @@ -63,7 +63,7 @@ internal sealed partial class AchievementDbBulkOperation if (entity is null && uiaf is not null) { - appDbContext.Achievements.AddAndSave(EntityAchievement.Create(archiveId, uiaf)); + appDbContext.Achievements.AddAndSave(EntityAchievement.From(archiveId, uiaf)); add++; continue; } @@ -86,7 +86,7 @@ internal sealed partial class AchievementDbBulkOperation if (aggressive) { appDbContext.Achievements.RemoveAndSave(entity); - appDbContext.Achievements.AddAndSave(EntityAchievement.Create(archiveId, uiaf)); + appDbContext.Achievements.AddAndSave(EntityAchievement.From(archiveId, uiaf)); update++; } } @@ -96,7 +96,7 @@ internal sealed partial class AchievementDbBulkOperation moveEntity = false; moveUIAF = true; - appDbContext.Achievements.AddAndSave(EntityAchievement.Create(archiveId, uiaf)); + appDbContext.Achievements.AddAndSave(EntityAchievement.From(archiveId, uiaf)); add++; } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.Interchange.cs b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.Interchange.cs index 887e4931..36d19d55 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.Interchange.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.Interchange.cs @@ -37,7 +37,7 @@ internal sealed partial class AchievementService case ImportStrategy.Overwrite: { IEnumerable orederedUIAF = list - .Select(uiaf => EntityAchievement.Create(archiveId, uiaf)) + .Select(uiaf => EntityAchievement.From(archiveId, uiaf)) .OrderBy(a => a.Id); return achievementDbBulkOperation.Overwrite(archiveId, orederedUIAF); } @@ -58,7 +58,7 @@ internal sealed partial class AchievementService List list = appDbContext.Achievements .Where(i => i.ArchiveId == archive.InnerId) .AsEnumerable() - .Select(i => i.ToUIAFItem()) + .Select(UIAFItem.From) .ToList(); return new() diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs index 2e28d7df..2b1e6f20 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs @@ -52,7 +52,7 @@ internal sealed partial class AchievementService : IAchievementService return metadata.SelectList(meta => { - EntityAchievement entity = entityMap.GetValueOrDefault(meta.Id) ?? EntityAchievement.Create(archive.InnerId, meta.Id); + EntityAchievement entity = entityMap.GetValueOrDefault(meta.Id) ?? EntityAchievement.From(archive.InnerId, meta.Id); return new AchievementView(entity, meta); }); } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoDbBulkOperation.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoDbBulkOperation.cs index 4f7bb44a..f7880681 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoDbBulkOperation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoDbBulkOperation.cs @@ -204,7 +204,7 @@ internal sealed partial class AvatarInfoDbBulkOperation { EnkaAvatarInfo avatarInfo = new() { AvatarId = avatarId }; transformer.Transform(ref avatarInfo, source); - entity = ModelAvatarInfo.Create(uid, avatarInfo); + entity = ModelAvatarInfo.From(uid, avatarInfo); appDbContext.AvatarInfos.AddAndSave(entity); } else @@ -221,7 +221,7 @@ internal sealed partial class AvatarInfoDbBulkOperation { if (entity == null) { - entity = ModelAvatarInfo.Create(uid, webInfo); + entity = ModelAvatarInfo.From(uid, webInfo); appDbContext.AvatarInfos.AddAndSave(entity); } else diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs index 610d9852..2b074172 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs @@ -222,14 +222,14 @@ internal sealed partial class CultivationService : ICultivationService if (entry == null) { - entry = CultivateEntry.Create(projectId, type, itemId); + entry = CultivateEntry.From(projectId, type, itemId); await appDbContext.CultivateEntries.AddAndSaveAsync(entry).ConfigureAwait(false); } Guid entryId = entry.InnerId; await appDbContext.CultivateItems.ExecuteDeleteWhereAsync(i => i.EntryId == entryId).ConfigureAwait(false); - IEnumerable toAdd = items.Select(i => CultivateItem.Create(entryId, i.Id, i.Num)); + IEnumerable toAdd = items.Select(item => CultivateItem.From(entryId, item)); await appDbContext.CultivateItems.AddRangeAndSaveAsync(toAdd).ConfigureAwait(false); } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs index 796dac37..6ce0995d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs @@ -48,7 +48,7 @@ internal sealed partial class DailyNoteService : IDailyNoteService, IRecipient n.Uid == roleUid)) { - DailyNoteEntry newEntry = DailyNoteEntry.Create(role); + DailyNoteEntry newEntry = DailyNoteEntry.From(role); Web.Response.Response dailyNoteResponse = await scope.ServiceProvider .PickRequiredService(PlayerUid.IsOversea(roleUid)) diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/HutaoCloudService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/HutaoCloudService.cs index 3bab09bb..543df1cf 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/HutaoCloudService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/HutaoCloudService.cs @@ -76,7 +76,7 @@ internal sealed partial class HutaoCloudService : IHutaoCloudService { if (archive == null) { - archive = Model.Entity.GachaArchive.Create(uid); + archive = Model.Entity.GachaArchive.From(uid); await appDbContext.GachaArchives.AddAndSaveAsync(archive).ConfigureAwait(false); } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs index 6bcddc13..1e9bdc2e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs @@ -32,7 +32,7 @@ internal sealed partial class GameService : IGameService private readonly PackageConverter packageConverter; private readonly IServiceProvider serviceProvider; private readonly LaunchOptions launchOptions; - private readonly HutaoOptions hutaoOptions; + private readonly RuntimeOptions hutaoOptions; private readonly ITaskContext taskContext; private readonly AppOptions appOptions; @@ -302,7 +302,7 @@ internal sealed partial class GameService : IGameService /// public async ValueTask DetectGameAccountAsync() { - Must.NotNull(gameAccounts!); + ArgumentNullException.ThrowIfNull(gameAccounts); string? registrySdk = RegistryInterop.Get(); if (!string.IsNullOrEmpty(registrySdk)) @@ -350,7 +350,7 @@ internal sealed partial class GameService : IGameService /// public GameAccount? DetectCurrentGameAccount() { - Must.NotNull(gameAccounts!); + ArgumentNullException.ThrowIfNull(gameAccounts); string? registrySdk = RegistryInterop.Get(); 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 38c3d98a..aec1f517 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverter.cs @@ -203,7 +203,7 @@ internal sealed partial class PackageConverter } // Cache folder - Core.HutaoOptions hutaoOptions = serviceProvider.GetRequiredService(); + Core.RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); string cacheFolder = Path.Combine(hutaoOptions.DataFolder, "ServerCache"); // 执行下载与移动操作 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataOptions.cs index ff388d37..24ad480f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataOptions.cs @@ -19,7 +19,7 @@ internal sealed partial class MetadataOptions : IOptions private readonly AppOptions appOptions; - private readonly HutaoOptions hutaoOptions; + private readonly RuntimeOptions hutaoOptions; private string? localeName; private string? fallbackDataFolder; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs index 79e3d840..14dca10e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs @@ -43,7 +43,8 @@ internal sealed partial class MetadataService if (memoryCache.TryGetValue(cacheKey, out object? value)) { - return Must.NotNull((Dictionary)value!); + ArgumentNullException.ThrowIfNull(value); + return (Dictionary)value; } Dictionary displays = await FromCacheAsDictionaryAsync(FileNameDisplayItem, a => a.Id, token).ConfigureAwait(false); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs index 95609d21..d8b35b95 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs @@ -167,7 +167,8 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi if (memoryCache.TryGetValue(cacheKey, out object? value)) { - return Must.NotNull((T)value!); + ArgumentNullException.ThrowIfNull(value); + return (T)value; } string path = metadataOptions.GetLocalizedLocalFile($"{fileName}.json"); @@ -176,7 +177,8 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi using (Stream fileStream = File.OpenRead(path)) { T? result = await JsonSerializer.DeserializeAsync(fileStream, options, token).ConfigureAwait(false); - return memoryCache.Set(cacheKey, Must.NotNull(result!)); + ArgumentNullException.ThrowIfNull(result); + return memoryCache.Set(cacheKey, result); } } else @@ -193,11 +195,12 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi if (memoryCache.TryGetValue(cacheKey, out object? value)) { - return Must.NotNull((Dictionary)value!); + ArgumentNullException.ThrowIfNull(value); + return (Dictionary)value; } List list = await FromCacheOrFileAsync>(fileName, token).ConfigureAwait(false); - Dictionary dict = list.ToDictionaryOverride(keySelector); + Dictionary dict = list.ToDictionaryIgnoringDuplicateKeys(keySelector); // There are duplicate name items return memoryCache.Set(cacheKey, dict); } @@ -208,11 +211,12 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi if (memoryCache.TryGetValue(cacheKey, out object? value)) { - return Must.NotNull((Dictionary)value!); + ArgumentNullException.ThrowIfNull(value); + return (Dictionary)value; } List list = await FromCacheOrFileAsync>(fileName, token).ConfigureAwait(false); - Dictionary dict = list.ToDictionaryOverride(keySelector, valueSelector); + Dictionary dict = list.ToDictionaryIgnoringDuplicateKeys(keySelector, valueSelector); // There are duplicate name items return memoryCache.Set(cacheKey, dict); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Navigation/NavigationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Navigation/NavigationService.cs index 964224e6..b15716c2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Navigation/NavigationService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Navigation/NavigationService.cs @@ -41,7 +41,8 @@ internal sealed partial class NavigationService : INavigationService, INavigatio navigationView.PaneOpened -= OnPaneStateChanged; } - navigationView = Must.NotNull(value!); + ArgumentNullException.ThrowIfNull(value); + navigationView = value; // add new listener if (navigationView != null) diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/CultivateProjectDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/CultivateProjectDialog.xaml.cs index 69d165d4..b93b775e 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/CultivateProjectDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/CultivateProjectDialog.xaml.cs @@ -42,7 +42,7 @@ internal sealed partial class CultivateProjectDialog : ContentDialog ? Ioc.Default.GetRequiredService().Current?.SelectedUserGameRole?.GameUid : null; - return new(true, CultivateProject.Create(text, uid)); + return new(true, CultivateProject.From(text, uid)); } return new(false, null!); diff --git a/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs index ae5d380f..ab24d69f 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs @@ -28,7 +28,7 @@ internal sealed partial class TitleView : UserControl { get { - Core.HutaoOptions hutaoOptions = Ioc.Default.GetRequiredService(); + Core.RuntimeOptions hutaoOptions = Ioc.Default.GetRequiredService(); string format = #if DEBUG diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs index 3c48e742..ec97b7b6 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs @@ -202,7 +202,7 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav if (isOk) { - ArchiveAddResult result = await achievementService.TryAddArchiveAsync(EntityAchievementArchive.Create(name)).ConfigureAwait(false); + ArchiveAddResult result = await achievementService.TryAddArchiveAsync(EntityAchievementArchive.From(name)).ConfigureAwait(false); switch (result) { @@ -230,7 +230,7 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav if (Archives != null && SelectedArchive != null) { ContentDialogResult result = await contentDialogFactory - .ConfirmCancelAsync( + .CreateForConfirmCancelAsync( string.Format(SH.ViewModelAchievementRemoveArchiveTitle, SelectedArchive.Name), SH.ViewModelAchievementRemoveArchiveContent) .ConfigureAwait(false); diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarView.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarView.cs index 4432dc38..5ddffe75 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarView.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarView.cs @@ -106,6 +106,6 @@ internal sealed class AvatarView : INameIconSide, ICalculableSource public ICalculableAvatar ToCalculable() { - return new CalculableAvatar(this); + return CalculableAvatar.From(this); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/SkillView.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/SkillView.cs index 5a6e899b..91607545 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/SkillView.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/SkillView.cs @@ -36,6 +36,6 @@ internal sealed class SkillView : NameIconDescription, ICalculableSource public ICalculableSkill ToCalculable() { - return new CalculableSkill(this); + return CalculableSkill.From(this); } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/WeaponView.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/WeaponView.cs index f7225181..62e6f522 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/WeaponView.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/WeaponView.cs @@ -55,6 +55,6 @@ internal sealed class WeaponView : Equip, ICalculableSource /// public ICalculableWeapon ToCalculable() { - return new CalculableWeapon(this); + return CalculableWeapon.From(this); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs index 2d9e9703..f88b43ad 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs @@ -25,14 +25,14 @@ internal sealed partial class ExperimentalFeaturesViewModel : ObservableObject [Command("OpenCacheFolderCommand")] private Task OpenCacheFolderAsync() { - HutaoOptions hutaoOptions = serviceProvider.GetRequiredService(); + RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); return Launcher.LaunchFolderPathAsync(hutaoOptions.LocalCache).AsTask(); } [Command("OpenDataFolderCommand")] private Task OpenDataFolderAsync() { - HutaoOptions hutaoOptions = serviceProvider.GetRequiredService(); + RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); return Launcher.LaunchFolderPathAsync(hutaoOptions.DataFolder).AsTask(); } @@ -43,7 +43,7 @@ internal sealed partial class ExperimentalFeaturesViewModel : ObservableObject { ContentDialogResult result = await scope.ServiceProvider .GetRequiredService() - .ConfirmCancelAsync(SH.ViewDialogSettingDeleteUserDataTitle, SH.ViewDialogSettingDeleteUserDataContent) + .CreateForConfirmCancelAsync(SH.ViewDialogSettingDeleteUserDataTitle, SH.ViewDialogSettingDeleteUserDataContent) .ConfigureAwait(false); if (result == ContentDialogResult.Primary) diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModel.cs index a7460206..72d45ed6 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModel.cs @@ -223,7 +223,7 @@ internal sealed partial class GachaLogViewModel : Abstraction.ViewModel } else { - await contentDialogFactory.ConfirmAsync(SH.ViewModelImportWarningTitle, SH.ViewModelImportWarningMessage).ConfigureAwait(false); + await contentDialogFactory.CreateForConfirmAsync(SH.ViewModelImportWarningTitle, SH.ViewModelImportWarningMessage).ConfigureAwait(false); } } } @@ -267,7 +267,7 @@ internal sealed partial class GachaLogViewModel : Abstraction.ViewModel if (Archives != null && SelectedArchive != null) { ContentDialogResult result = await contentDialogFactory - .ConfirmCancelAsync(string.Format(SH.ViewModelGachaLogRemoveArchiveTitle, SelectedArchive.Uid), SH.ViewModelGachaLogRemoveArchiveDescription) + .CreateForConfirmCancelAsync(string.Format(SH.ViewModelGachaLogRemoveArchiveTitle, SelectedArchive.Uid), SH.ViewModelGachaLogRemoveArchiveDescription) .ConfigureAwait(false); if (result == ContentDialogResult.Primary) diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs index 8c9ba1e6..589cb205 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs @@ -35,7 +35,7 @@ internal sealed partial class LaunchGameViewModel : Abstraction.ViewModel private readonly IServiceProvider serviceProvider; private readonly LaunchOptions launchOptions; - private readonly HutaoOptions hutaoOptions; + private readonly RuntimeOptions hutaoOptions; private readonly ITaskContext taskContext; private readonly IGameService gameService; private readonly IMemoryCache memoryCache; @@ -86,7 +86,7 @@ internal sealed partial class LaunchGameViewModel : Abstraction.ViewModel /// /// 胡桃选项 /// - public HutaoOptions HutaoOptions { get => hutaoOptions; } + public RuntimeOptions HutaoOptions { get => hutaoOptions; } /// /// 应用选项 diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs index 0df40a27..faf5a048 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs @@ -39,7 +39,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel private readonly IGameService gameService; private readonly ILogger logger; private readonly AppOptions options; - private readonly HutaoOptions hutaoOptions; + private readonly RuntimeOptions hutaoOptions; private readonly HutaoUserOptions hutaoUserOptions; private readonly ExperimentalFeaturesViewModel experimental; @@ -54,7 +54,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel /// /// 胡桃选项 /// - public HutaoOptions HutaoOptions { get => hutaoOptions; } + public RuntimeOptions HutaoOptions { get => hutaoOptions; } /// /// 胡桃用户选项 diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs index 76fd6db1..436e914d 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs @@ -25,7 +25,7 @@ internal sealed partial class UserViewModel : ObservableObject { private readonly IServiceProvider serviceProvider; private readonly IInfoBarService infoBarService; - private readonly Core.HutaoOptions hutaoOptions; + private readonly Core.RuntimeOptions hutaoOptions; private readonly ITaskContext taskContext; private readonly IUserService userService; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs index 7d5c4b01..724f591d 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs @@ -70,7 +70,7 @@ internal sealed partial class WelcomeViewModel : ObservableObject { Dictionary downloadSummaries = new(); - if (StaticResource.IsContractUnfulfilled(SettingKeys.StaticResourceV1Contract)) + if (StaticResource.IsContractUnfulfilled(StaticResource.V1Contract)) { downloadSummaries.TryAdd("Bg", new(serviceProvider, "Bg")); downloadSummaries.TryAdd("AvatarIcon", new(serviceProvider, "AvatarIcon")); @@ -83,7 +83,7 @@ internal sealed partial class WelcomeViewModel : ObservableObject downloadSummaries.TryAdd("Talent", new(serviceProvider, "Talent")); } - if (StaticResource.IsContractUnfulfilled(SettingKeys.StaticResourceV2Contract)) + if (StaticResource.IsContractUnfulfilled(StaticResource.V2Contract)) { downloadSummaries.TryAdd("AchievementIcon", new(serviceProvider, "AchievementIcon")); downloadSummaries.TryAdd("ItemIcon", new(serviceProvider, "ItemIcon")); @@ -91,18 +91,18 @@ internal sealed partial class WelcomeViewModel : ObservableObject downloadSummaries.TryAdd("RelicIcon", new(serviceProvider, "RelicIcon")); } - if (StaticResource.IsContractUnfulfilled(SettingKeys.StaticResourceV3Contract)) + if (StaticResource.IsContractUnfulfilled(StaticResource.V3Contract)) { downloadSummaries.TryAdd("Skill", new(serviceProvider, "Skill")); downloadSummaries.TryAdd("Talent", new(serviceProvider, "Talent")); } - if (StaticResource.IsContractUnfulfilled(SettingKeys.StaticResourceV4Contract)) + if (StaticResource.IsContractUnfulfilled(StaticResource.V4Contract)) { downloadSummaries.TryAdd("AvatarIcon", new(serviceProvider, "AvatarIcon")); } - if (StaticResource.IsContractUnfulfilled(SettingKeys.StaticResourceV5Contract)) + if (StaticResource.IsContractUnfulfilled(StaticResource.V5Contract)) { downloadSummaries.TryAdd("MonsterIcon", new(serviceProvider, "MonsterIcon")); } @@ -134,7 +134,7 @@ internal sealed partial class WelcomeViewModel : ObservableObject { taskContext = serviceProvider.GetRequiredService(); httpClient = serviceProvider.GetRequiredService(); - HutaoOptions hutaoOptions = serviceProvider.GetRequiredService(); + RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(hutaoOptions.UserAgent); this.serviceProvider = serviceProvider; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaLogUploadClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaLogUploadClient.cs index cc179859..dccd6e6c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaLogUploadClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaLogUploadClient.cs @@ -45,7 +45,7 @@ internal sealed class HomaLogUploadClient private static HutaoLog BuildFromException(IServiceProvider serviceProvider, Exception exception) { - HutaoOptions hutaoOptions = serviceProvider.GetRequiredService(); + RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService(); return new() {