From d7dd8c6f0dbe43cfb800ab06981e18a01061bc52 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Fri, 10 Feb 2023 16:07:01 +0800 Subject: [PATCH] code style --- src/Snap.Hutao/Snap.Hutao/App.xaml.cs | 1 - .../Extension/ContentDialogExtension.cs | 1 + .../Control/Image/CompositionImage.cs | 1 - .../Annotation/LocalizationKeyAttribute.cs | 8 +-- src/Snap.Hutao/Snap.Hutao/Core/IO/TempFile.cs | 10 ++- .../Snap.Hutao/Core/LifeCycle/Activation.cs | 2 +- .../Core/Windowing/ExtendedWindow.cs | 1 - .../Model/Entity/SpiralAbyssEntry.cs | 2 +- .../Resource/Localization/SH.Designer.cs | 45 +++++++++++++ .../Snap.Hutao/Resource/Localization/SH.resx | 15 +++++ .../Service/Achievement/AchievementService.cs | 1 - .../Service/Cultivation/CultivationService.cs | 26 +++++++- .../Cultivation/ICultivationService.cs | 1 - .../Service/DailyNote/DailyNoteNotifier.cs | 1 - .../Service/GachaLog/GachaLogService.cs | 5 +- .../GachaLogQueryWebCacheProvider.cs | 2 +- .../Snap.Hutao/Service/Game/GameService.cs | 5 +- .../Game/Package/PackageConvertException.cs | 9 --- .../Service/Metadata/MetadataService.cs | 16 +++-- .../Service/Navigation/NavigationService.cs | 1 - .../SpiralAbyss/SpiralAbyssRecordService.cs | 57 +++++----------- .../Snap.Hutao/Service/User/UserService.cs | 2 +- .../Control/AnnouncementContentViewer.xaml.cs | 6 +- .../View/Control/StatisticsCard.xaml.cs | 4 +- .../GachaLogRefreshProgressDialog.xaml.cs | 1 - .../LaunchGamePackageConvertDialog.xaml.cs | 4 +- .../View/Page/LoginMihoyoUserPage.xaml.cs | 23 ++++--- .../Snap.Hutao/View/Page/SettingPage.xaml.cs | 2 - .../View/Page/SpiralAbyssRecordPage.xaml | 2 +- .../View/Page/WikiAvatarPage.xaml.cs | 2 - .../ViewModel/Abstraction/ViewModel.cs | 2 +- .../Achievement/AchievementViewModel.cs | 2 - .../ViewModel/AvatarPropertyViewModel.cs | 65 +++++++++---------- .../ViewModel/DailyNoteViewModel.cs | 28 ++++---- .../ExperimentalFeaturesViewModel.cs | 11 +++- .../Snap.Hutao/ViewModel/GachaLogViewModel.cs | 22 +++---- .../ViewModel/HutaoDatabaseViewModel.cs | 6 -- .../ViewModel/LaunchGameViewModel.cs | 39 +++++------ .../Snap.Hutao/ViewModel/SettingViewModel.cs | 37 +++++------ .../ViewModel/SpiralAbyssRecordViewModel.cs | 38 +++++------ .../Snap.Hutao/ViewModel/TestViewModel.cs | 16 +++-- .../Snap.Hutao/ViewModel/UserViewModel.cs | 12 ++-- .../Snap.Hutao/ViewModel/WelcomeViewModel.cs | 17 +++-- .../ViewModel/WikiAvatarViewModel.cs | 44 ++++++++----- .../ViewModel/WikiWeaponViewModel.cs | 43 +++++++----- .../DynamicSecret/DynamicSecretHandler.cs | 1 - .../Snap.Hutao/Web/HttpClientExtensions.cs | 1 - 47 files changed, 353 insertions(+), 287 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/App.xaml.cs b/src/Snap.Hutao/Snap.Hutao/App.xaml.cs index 4f7fbe6e..e5a020ae 100644 --- a/src/Snap.Hutao/Snap.Hutao/App.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/App.xaml.cs @@ -7,7 +7,6 @@ using Microsoft.Windows.AppLifecycle; using Snap.Hutao.Core; using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Core.LifeCycle; -using Snap.Hutao.Core.Logging; using System.Diagnostics; using Windows.Storage; diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Extension/ContentDialogExtension.cs b/src/Snap.Hutao/Snap.Hutao/Control/Extension/ContentDialogExtension.cs index 5eaab145..3bac06ef 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Extension/ContentDialogExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Extension/ContentDialogExtension.cs @@ -21,6 +21,7 @@ internal static class ContentDialogExtension contentDialog.ShowAsync().AsTask().SafeForget(); // E_ASYNC_OPERATION_NOT_STARTED 0x80000019 + // Only a single ContentDialog can be open at any time. return new ContentDialogHider(contentDialog); } diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs b/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs index 1e5cf33f..813be0f3 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs @@ -12,7 +12,6 @@ using Snap.Hutao.Extension; using Snap.Hutao.Service.Abstraction; using System.IO; using System.Net.Http; -using System.Reflection; using System.Runtime.InteropServices; namespace Snap.Hutao.Control.Image; diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Annotation/LocalizationKeyAttribute.cs b/src/Snap.Hutao/Snap.Hutao/Core/Annotation/LocalizationKeyAttribute.cs index d43b7f82..1fb583f7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Annotation/LocalizationKeyAttribute.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Annotation/LocalizationKeyAttribute.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Snap.Hutao.Core.Annotation; +namespace Snap.Hutao.Core.Annotation; /// /// 本地化键 diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/TempFile.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/TempFile.cs index 0d32b5e3..cd3774a2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/TempFile.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/TempFile.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.ExceptionService; using System.IO; namespace Snap.Hutao.Core.IO; @@ -16,7 +17,14 @@ internal sealed class TempFile : IDisposable /// 是否在创建时删除文件 public TempFile(bool delete = false) { - Path = System.IO.Path.GetTempFileName(); + try + { + Path = System.IO.Path.GetTempFileName(); + } + catch (UnauthorizedAccessException ex) + { + throw ThrowHelper.RuntimeEnvironment(SH.CoreIOTempFileCreateFail, ex); + } if (delete) { diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/Activation.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/Activation.cs index 7245cfb2..172de3c2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/Activation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/Activation.cs @@ -109,7 +109,7 @@ internal static class Activation private static async Task HandleActivationCoreAsync(AppActivationArguments args, bool isRedirected) { - if (args.Kind == ExtendedActivationKind.Protocol) + if (args.Kind == ExtendedActivationKind.Protocol) { if (args.TryGetProtocolActivatedUri(out Uri? uri)) { diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs index 92cfb10f..957ae450 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs @@ -10,7 +10,6 @@ using Snap.Hutao.Extension; using Snap.Hutao.Message; using Snap.Hutao.Win32; using System.IO; -using Windows.ApplicationModel; using Windows.Graphics; using Windows.UI; using Windows.Win32.Foundation; diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs index 7d02971d..fb850071 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs @@ -29,7 +29,7 @@ public class SpiralAbyssEntry : ObservableObject /// 计划名称 /// [NotMapped] - public string Schedule { get => $"第 {ScheduleId} 期"; } + public string Schedule { get => string.Format(SH.ModelEntitySpiralAbyssScheduleFormat, ScheduleId); } /// /// Uid diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs index d5f169ac..ce4382f5 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs @@ -195,6 +195,15 @@ namespace Snap.Hutao.Resource.Localization { } } + /// + /// 查找类似 权限不足,创建临时文件失败 的本地化字符串。 + /// + internal static string CoreIOTempFileCreateFail { + get { + return ResourceManager.GetString("CoreIOTempFileCreateFail", resourceCulture); + } + } + /// /// 查找类似 启动游戏 的本地化字符串。 /// @@ -339,6 +348,15 @@ namespace Snap.Hutao.Resource.Localization { } } + /// + /// 查找类似 第 {0} 期 的本地化字符串。 + /// + internal static string ModelEntitySpiralAbyssScheduleFormat { + get { + return ResourceManager.GetString("ModelEntitySpiralAbyssScheduleFormat", resourceCulture); + } + } + /// /// 查找类似 必须先选择一个用户与角色 的本地化字符串。 /// @@ -357,6 +375,24 @@ namespace Snap.Hutao.Resource.Localization { } } + /// + /// 查找类似 保存养成计划状态失败 的本地化字符串。 + /// + internal static string ServiceCultivationProjectCurrentUserdataCourrpted { + get { + return ResourceManager.GetString("ServiceCultivationProjectCurrentUserdataCourrpted", resourceCulture); + } + } + + /// + /// 查找类似 存在多个选中的养成计划 的本地化字符串。 + /// + internal static string ServiceCultivationProjectCurrentUserdataCourrpted2 { + get { + return ResourceManager.GetString("ServiceCultivationProjectCurrentUserdataCourrpted2", resourceCulture); + } + } + /// /// 查找类似 开始游戏 的本地化字符串。 /// @@ -1437,6 +1473,15 @@ namespace Snap.Hutao.Resource.Localization { } } + /// + /// 查找类似 养成计划添加失败 的本地化字符串。 + /// + internal static string ViewModelCultivationAddWarning { + get { + return ResourceManager.GetString("ViewModelCultivationAddWarning", resourceCulture); + } + } + /// /// 查找类似 已成功添加至当前养成计划 的本地化字符串。 /// diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index 958603bd..c7e329b2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -162,6 +162,9 @@ 无法打开文件选择器 + + 权限不足,创建临时文件失败 + 启动游戏 @@ -210,12 +213,21 @@ {0} 抽 + + 第 {0} 期 + 必须先选择一个用户与角色 单个成就存档内发现多个相同的成就 Id + + 保存养成计划状态失败 + + + 存在多个选中的养成计划 + 开始游戏 @@ -576,6 +588,9 @@ 角色展柜尚未开启,请前往游戏操作后重试 + + 养成计划添加失败 + 已成功添加至当前养成计划 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs index 95b359bd..2e59358b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs @@ -6,7 +6,6 @@ using Microsoft.EntityFrameworkCore; using Snap.Hutao.Core.Database; using Snap.Hutao.Core.Diagnostics; using Snap.Hutao.Core.ExceptionService; -using Snap.Hutao.Core.Logging; using Snap.Hutao.Extension; using Snap.Hutao.Model.Entity.Database; using Snap.Hutao.Model.InterChange.Achievement; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs index 0601f9e8..fd1e78f4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs @@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.Messaging; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Snap.Hutao.Core.Database; +using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Extension; using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity.Database; @@ -55,10 +56,21 @@ internal class CultivationService : ICultivationService using (IServiceScope scope = scopeFactory.CreateScope()) { AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService(); - projects = new(appDbContext.CultivateProjects.AsNoTracking().ToList()); + projects = appDbContext.CultivateProjects.AsNoTracking().ToObservableCollection(); } - Current ??= projects.SingleOrDefault(proj => proj.IsSelected); + try + { + Current ??= projects.SingleOrDefault(proj => proj.IsSelected); + } + catch (DbUpdateConcurrencyException ex) + { + ThrowHelper.UserdataCorrupted(SH.ServiceCultivationProjectCurrentUserdataCourrpted, ex); + } + catch (InvalidOperationException ex) + { + ThrowHelper.UserdataCorrupted(SH.ServiceCultivationProjectCurrentUserdataCourrpted2, ex); + } } return projects; @@ -277,7 +289,15 @@ internal class CultivationService : ICultivationService { AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService(); - Current ??= appDbContext.CultivateProjects.AsNoTracking().SingleOrDefault(proj => proj.IsSelected); + try + { + Current ??= appDbContext.CultivateProjects.AsNoTracking().SingleOrDefault(proj => proj.IsSelected); + } + catch (InvalidOperationException ex) + { + ThrowHelper.UserdataCorrupted(SH.ServiceCultivationProjectCurrentUserdataCourrpted2, ex); + } + if (Current == null) { return false; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs index 5fb5fc86..429f80b7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs @@ -4,7 +4,6 @@ using Snap.Hutao.Model.Binding.Cultivation; using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Metadata; -using Snap.Hutao.Model.Primitive; using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate; using System.Collections.ObjectModel; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotifier.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotifier.cs index a62c991e..ec667d64 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotifier.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteNotifier.cs @@ -6,7 +6,6 @@ using Microsoft.Extensions.DependencyInjection; using Snap.Hutao.Core.Database; using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity.Database; -using Snap.Hutao.Model.Metadata.Converter; using Snap.Hutao.Web.Hoyolab.Takumi.Auth; using Snap.Hutao.Web.Hoyolab.Takumi.Binding; using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.DailyNote; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs index 1ca8a677..38acef09 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs @@ -16,7 +16,6 @@ using Snap.Hutao.Model.Entity.Database; using Snap.Hutao.Model.InterChange.GachaLog; using Snap.Hutao.Model.Metadata.Abstraction; using Snap.Hutao.Model.Primitive; -using Snap.Hutao.Service.Abstraction; using Snap.Hutao.Service.GachaLog.Factory; using Snap.Hutao.Service.GachaLog.QueryProvider; using Snap.Hutao.Service.Metadata; @@ -122,7 +121,7 @@ internal class GachaLogService : IGachaLogService await ThreadHelper.SwitchToMainThreadAsync(); try { - archiveCollection ??= appDbContext.GachaArchives.AsNoTracking().ToObservableCollection(); + archiveCollection ??= appDbContext.GachaArchives.AsNoTracking().ToObservableCollection(); } catch (SqliteException ex) { @@ -329,6 +328,8 @@ internal class GachaLogService : IGachaLogService GachaArchive created = GachaArchive.Create(uid); appDbContext.GachaArchives.AddAndSave(created); + // System.InvalidOperationException: Sequence contains no elements + // ? how this happen here? archive = appDbContext.GachaArchives.Single(a => a.Uid == uid); GachaArchive temp = archive; ThreadHelper.InvokeOnMainThread(() => archiveCollection!.Add(temp)); 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 b167691f..5c285a2c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs @@ -48,7 +48,7 @@ internal class GachaLogQueryWebCacheProvider : IGachaLogQueryProvider { (bool isOk, string path) = await gameService.GetGamePathAsync().ConfigureAwait(false); - if (isOk) + if (isOk && (!string.IsNullOrEmpty(path))) { string cacheFile = GetCacheFile(path); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs index 28f8a715..41d9b1c4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs @@ -59,14 +59,13 @@ internal class GameService : IGameService { if (memoryCache.TryGetValue(GamePathKey, out object? value)) { - return new(true, Must.NotNull((value as string)!)); + return new(true, (value as string)!); } else { using (IServiceScope scope = scopeFactory.CreateScope()) { AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService(); - SettingEntry entry = await appDbContext.Settings.SingleOrAddAsync(SettingEntry.GamePath, string.Empty).ConfigureAwait(false); // Cannot find in setting @@ -89,7 +88,7 @@ internal class GameService : IGameService { // Save result. entry.Value = result.Value; - appDbContext.Settings.UpdateAndSave(entry); + await appDbContext.Settings.UpdateAndSaveAsync(entry).ConfigureAwait(false); } else { diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConvertException.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConvertException.cs index 747c7937..c4329da7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConvertException.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConvertException.cs @@ -1,15 +1,6 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; -using Snap.Hutao.Core.IO; -using Snap.Hutao.Model.Binding.LaunchGame; -using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher; -using System.IO; -using System.IO.Compression; -using System.Net.Http; -using static Snap.Hutao.Service.Game.GameConstants; - namespace Snap.Hutao.Service.Game.Package; /// diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs index 990d7fd2..9974c5f3 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Caching.Memory; using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; using Snap.Hutao.Core.Diagnostics; +using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Core.IO; using Snap.Hutao.Core.Logging; using Snap.Hutao.Extension; @@ -11,7 +12,6 @@ using Snap.Hutao.Service.Abstraction; using System.IO; using System.Net.Http; using System.Net.Http.Json; -using System.Security.Cryptography; namespace Snap.Hutao.Service.Metadata; @@ -180,10 +180,18 @@ internal partial class MetadataService : IMetadataService, IMetadataServiceIniti return Must.NotNull((T)value!); } - using (Stream fileStream = File.OpenRead(Path.Combine(metadataFolderPath, $"{fileName}.json"))) + string path = Path.Combine(metadataFolderPath, $"{fileName}.json"); + if (File.Exists(path)) { - T? result = await JsonSerializer.DeserializeAsync(fileStream, options, token).ConfigureAwait(false); - return memoryCache.Set(cacheKey, Must.NotNull(result!)); + using (Stream fileStream = File.OpenRead(path)) + { + T? result = await JsonSerializer.DeserializeAsync(fileStream, options, token).ConfigureAwait(false); + return memoryCache.Set(cacheKey, Must.NotNull(result!)); + } + } + else + { + throw ThrowHelper.UserdataCorrupted(SH.ServiceMetadataNotInitialized, null!); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Navigation/NavigationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Navigation/NavigationService.cs index 28abd4d6..b2196e2e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Navigation/NavigationService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Navigation/NavigationService.cs @@ -3,7 +3,6 @@ using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Control; -using Snap.Hutao.Core.Logging; using Snap.Hutao.Core.Setting; using Snap.Hutao.Service.Abstraction; using Snap.Hutao.View.Helper; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordService.cs b/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordService.cs index d7106c7a..2a0803c8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordService.cs @@ -63,61 +63,38 @@ internal class SpiralAbyssRecordService : ISpiralAbyssRecordService /// public async Task RefreshSpiralAbyssAsync(UserAndUid userAndUid) { - Response lastResponse = await gameRecordClient - .GetSpiralAbyssAsync(userAndUid, SpiralAbyssSchedule.Last) + await RefreshSpiralAbyssCoreAsync(userAndUid, SpiralAbyssSchedule.Last).ConfigureAwait(false); + await RefreshSpiralAbyssCoreAsync(userAndUid, SpiralAbyssSchedule.Current).ConfigureAwait(false); + } + + private async Task RefreshSpiralAbyssCoreAsync(UserAndUid userAndUid, SpiralAbyssSchedule schedule) + { + Response response = await gameRecordClient + .GetSpiralAbyssAsync(userAndUid, schedule) .ConfigureAwait(false); - if (lastResponse.IsOk()) + if (response.IsOk()) { - Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss last = lastResponse.Data; + Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss webSpiralAbyss = response.Data; - SpiralAbyssEntry? lastEntry = spiralAbysses!.SingleOrDefault(s => s.ScheduleId == last.ScheduleId); - if (lastEntry != null) + SpiralAbyssEntry? existEntry = spiralAbysses!.SingleOrDefault(s => s.ScheduleId == webSpiralAbyss.ScheduleId); + if (existEntry != null) { await ThreadHelper.SwitchToMainThreadAsync(); - lastEntry.UpdateSpiralAbyss(last); + existEntry.UpdateSpiralAbyss(webSpiralAbyss); await ThreadHelper.SwitchToBackgroundAsync(); - await appDbContext.SpiralAbysses.UpdateAndSaveAsync(lastEntry).ConfigureAwait(false); + await appDbContext.SpiralAbysses.UpdateAndSaveAsync(existEntry).ConfigureAwait(false); } else { - SpiralAbyssEntry entry = SpiralAbyssEntry.Create(userAndUid.Uid.Value, last); + SpiralAbyssEntry newEntry = SpiralAbyssEntry.Create(userAndUid.Uid.Value, webSpiralAbyss); await ThreadHelper.SwitchToMainThreadAsync(); - spiralAbysses!.Insert(0, entry); + spiralAbysses!.Insert(0, newEntry); await ThreadHelper.SwitchToBackgroundAsync(); - await appDbContext.SpiralAbysses.AddAndSaveAsync(entry).ConfigureAwait(false); - } - } - - Response currentResponse = await gameRecordClient - .GetSpiralAbyssAsync(userAndUid, SpiralAbyssSchedule.Current) - .ConfigureAwait(false); - - if (currentResponse.IsOk()) - { - Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss current = currentResponse.Data; - - SpiralAbyssEntry? currentEntry = spiralAbysses!.SingleOrDefault(s => s.ScheduleId == current.ScheduleId); - if (currentEntry != null) - { - await ThreadHelper.SwitchToMainThreadAsync(); - currentEntry.UpdateSpiralAbyss(current); - - await ThreadHelper.SwitchToBackgroundAsync(); - await appDbContext.SpiralAbysses.UpdateAndSaveAsync(currentEntry).ConfigureAwait(false); - } - else - { - SpiralAbyssEntry entry = SpiralAbyssEntry.Create(userAndUid.Uid.Value, current); - - await ThreadHelper.SwitchToMainThreadAsync(); - spiralAbysses!.Insert(0, entry); - - await ThreadHelper.SwitchToBackgroundAsync(); - await appDbContext.SpiralAbysses.AddAndSaveAsync(entry).ConfigureAwait(false); + await appDbContext.SpiralAbysses.AddAndSaveAsync(newEntry).ConfigureAwait(false); } } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs b/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs index 95c62397..ca8d60b5 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs @@ -99,7 +99,7 @@ internal class UserService : IUserService // Sync cache await ThreadHelper.SwitchToMainThreadAsync(); userCollection!.Remove(user); - roleCollection?.RemoveWhere(r => r.User.InnerId == user.Entity.InnerId); + roleCollection?.RemoveWhere(r => r.User.Mid == user.Entity.Mid); // Sync database await ThreadHelper.SwitchToBackgroundAsync(); diff --git a/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs index 3813892d..e1826709 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs @@ -2,11 +2,9 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Navigation; using Microsoft.Web.WebView2.Core; using Snap.Hutao.Control; using Snap.Hutao.Control.Theme; -using Snap.Hutao.Service.Navigation; using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement; using Windows.System; @@ -58,8 +56,8 @@ public sealed partial class AnnouncementContentViewer : Microsoft.UI.Xaml.Contro /// public Announcement Announcement { - get { return (Announcement)GetValue(AnnouncementProperty); } - set { SetValue(AnnouncementProperty, value); } + get => (Announcement)GetValue(AnnouncementProperty); + set => SetValue(AnnouncementProperty, value); } private static string? GenerateHtml(Announcement? announcement, ElementTheme theme) diff --git a/src/Snap.Hutao/Snap.Hutao/View/Control/StatisticsCard.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Control/StatisticsCard.xaml.cs index a89bc82f..00343889 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Control/StatisticsCard.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Control/StatisticsCard.xaml.cs @@ -27,7 +27,7 @@ public sealed partial class StatisticsCard : UserControl /// public bool ShowUpPull { - get { return (bool)GetValue(ShowUpPullProperty); } - set { SetValue(ShowUpPullProperty, value); } + get => (bool)GetValue(ShowUpPullProperty); + set => SetValue(ShowUpPullProperty, value); } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogRefreshProgressDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogRefreshProgressDialog.xaml.cs index 8cc8d18e..8700e962 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogRefreshProgressDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogRefreshProgressDialog.xaml.cs @@ -8,7 +8,6 @@ using Snap.Hutao.Extension; using Snap.Hutao.Model.Binding.Gacha.Abstraction; using Snap.Hutao.Service.GachaLog; using Snap.Hutao.View.Control; -using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo; namespace Snap.Hutao.View.Dialog; diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/LaunchGamePackageConvertDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/LaunchGamePackageConvertDialog.xaml.cs index 7948711c..9339907a 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/LaunchGamePackageConvertDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/LaunchGamePackageConvertDialog.xaml.cs @@ -30,7 +30,7 @@ public sealed partial class LaunchGamePackageConvertDialog : ContentDialog /// public PackageReplaceStatus State { - get { return (PackageReplaceStatus)GetValue(StateProperty); } - set { SetValue(StateProperty, value); } + get => (PackageReplaceStatus)GetValue(StateProperty); + set => SetValue(StateProperty, value); } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml.cs index 75338194..ea65fa0e 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml.cs @@ -29,16 +29,23 @@ public sealed partial class LoginMihoyoUserPage : Microsoft.UI.Xaml.Controls.Pag [SuppressMessage("", "VSTHRD100")] private async void OnRootLoaded(object sender, RoutedEventArgs e) { - await WebView.EnsureCoreWebView2Async(); - - CoreWebView2CookieManager manager = WebView.CoreWebView2.CookieManager; - IReadOnlyList cookies = await manager.GetCookiesAsync("https://user.mihoyo.com"); - foreach (CoreWebView2Cookie item in cookies) + try { - manager.DeleteCookie(item); - } + await WebView.EnsureCoreWebView2Async(); - WebView.CoreWebView2.Navigate("https://user.mihoyo.com/#/login/password"); + CoreWebView2CookieManager manager = WebView.CoreWebView2.CookieManager; + IReadOnlyList cookies = await manager.GetCookiesAsync("https://user.mihoyo.com"); + foreach (CoreWebView2Cookie item in cookies) + { + manager.DeleteCookie(item); + } + + WebView.CoreWebView2.Navigate("https://user.mihoyo.com/#/login/password"); + } + catch (Exception ex) + { + Ioc.Default.GetRequiredService().Error(ex); + } } private async Task HandleCurrentCookieAsync(CancellationToken token) diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml.cs index aa1d0702..5444cf72 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml.cs @@ -1,9 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Microsoft.UI.Xaml.Navigation; using Snap.Hutao.Control; -using Snap.Hutao.Service.Navigation; using Snap.Hutao.ViewModel; namespace Snap.Hutao.View.Page; diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/SpiralAbyssRecordPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/SpiralAbyssRecordPage.xaml index c73866b4..6cf0e29e 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/SpiralAbyssRecordPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/SpiralAbyssRecordPage.xaml @@ -21,7 +21,7 @@ - + /// 操作被用户取消 - protected void ThrowIfViewDisposed() + private void ThrowIfViewDisposed() { if (IsViewDisposed) { diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs index f5e9ba3a..64361e53 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs @@ -5,10 +5,8 @@ using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.WinUI.UI; using Microsoft.UI.Xaml.Controls; -using Snap.Hutao.Control.Extension; using Snap.Hutao.Core.Database; using Snap.Hutao.Core.IO; -using Snap.Hutao.Core.IO.DataTransfer; using Snap.Hutao.Core.LifeCycle; using Snap.Hutao.Extension; using Snap.Hutao.Factory.Abstraction; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarPropertyViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarPropertyViewModel.cs index 3322781d..f4ef7cfc 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarPropertyViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarPropertyViewModel.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using CommunityToolkit.Mvvm.Input; +using Microsoft.Extensions.DependencyInjection; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media.Imaging; @@ -18,7 +19,6 @@ using Snap.Hutao.Service.AvatarInfo; using Snap.Hutao.Service.Cultivation; using Snap.Hutao.Service.User; using Snap.Hutao.View.Dialog; -using Snap.Hutao.Web.Hoyolab.Takumi.Binding; using Snap.Hutao.Web.Response; using System.Runtime.InteropServices; using Windows.Graphics.Imaging; @@ -39,30 +39,21 @@ namespace Snap.Hutao.ViewModel; [Injection(InjectAs.Scoped)] internal class AvatarPropertyViewModel : Abstraction.ViewModel { + private readonly IServiceProvider serviceProvider; private readonly IUserService userService; - private readonly IAvatarInfoService avatarInfoService; private readonly IInfoBarService infoBarService; - private readonly IContentDialogFactory contentDialogFactory; private Summary? summary; private Avatar? selectedAvatar; /// /// 构造一个新的角色属性视图模型 /// - /// 用户服务 - /// 角色信息服务 - /// 对话框工厂 - /// 信息条服务 - public AvatarPropertyViewModel( - IUserService userService, - IAvatarInfoService avatarInfoService, - IContentDialogFactory contentDialogFactory, - IInfoBarService infoBarService) + /// 服务提供器 + public AvatarPropertyViewModel(IServiceProvider serviceProvider) { - this.userService = userService; - this.avatarInfoService = avatarInfoService; - this.infoBarService = infoBarService; - this.contentDialogFactory = contentDialogFactory; + userService = serviceProvider.GetRequiredService(); + infoBarService = serviceProvider.GetRequiredService(); + this.serviceProvider = serviceProvider; OpenUICommand = new AsyncRelayCommand(OpenUIAsync); RefreshFromEnkaApiCommand = new AsyncRelayCommand(RefreshByEnkaApiAsync); @@ -159,14 +150,18 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel ValueResult summaryResult; using (await EnterCriticalExecutionAsync().ConfigureAwait(false)) { - ContentDialog dialog = await contentDialogFactory + ContentDialog dialog = await serviceProvider + .GetRequiredService() .CreateForIndeterminateProgressAsync(SH.ViewModelAvatarPropertyFetch) .ConfigureAwait(false); await ThreadHelper.SwitchToMainThreadAsync(); await using (await dialog.BlockAsync().ConfigureAwait(false)) { - summaryResult = await avatarInfoService.GetSummaryAsync(userAndUid, option, token).ConfigureAwait(false); + summaryResult = await serviceProvider + .GetRequiredService() + .GetSummaryAsync(userAndUid, option, token) + .ConfigureAwait(false); } } @@ -199,9 +194,6 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel { if (avatar != null) { - IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); - IUserService userService = Ioc.Default.GetRequiredService(); - if (userService.Current != null) { if (avatar.Weapon == null) @@ -218,14 +210,14 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel if (isOk) { - Response consumptionResponse = await Ioc.Default + Response consumptionResponse = await serviceProvider .GetRequiredService() .ComputeAsync(userService.Current.Entity, delta) .ConfigureAwait(false); if (consumptionResponse.IsOk()) { - ICultivationService cultivationService = Ioc.Default.GetRequiredService(); + ICultivationService cultivationService = serviceProvider.GetRequiredService(); CalcConsumption consumption = consumptionResponse.Data; List items = CalcItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume); @@ -233,18 +225,25 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel .SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, items) .ConfigureAwait(false); - // take a hot path if avatar is not saved. - bool avatarAndWeaponSaved = avatarSaved && await cultivationService - .SaveConsumptionAsync(CultivateType.Weapon, avatar.Weapon.Id, consumption.WeaponConsume.EmptyIfNull()) - .ConfigureAwait(false); + try + { + // take a hot path if avatar is not saved. + bool avatarAndWeaponSaved = avatarSaved && await cultivationService + .SaveConsumptionAsync(CultivateType.Weapon, avatar.Weapon.Id, consumption.WeaponConsume.EmptyIfNull()) + .ConfigureAwait(false); - if (avatarAndWeaponSaved) - { - infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess); + if (avatarAndWeaponSaved) + { + infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess); + } + else + { + infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning); + } } - else + catch (Core.ExceptionService.UserdataCorruptedException ex) { - infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning); + infoBarService.Error(ex, SH.ViewModelCultivationAddWarning); } } } @@ -267,7 +266,7 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel bool clipboardOpened = false; using (SoftwareBitmap softwareBitmap = SoftwareBitmap.CreateCopyFromBuffer(buffer, BitmapPixelFormat.Bgra8, bitmap.PixelWidth, bitmap.PixelHeight)) { - Color tintColor = (Color)Ioc.Default.GetRequiredService().Resources["CompatBackgroundColor"]; + Color tintColor = (Color)serviceProvider.GetRequiredService().Resources["CompatBackgroundColor"]; Bgra8 tint = Bgra8.FromColor(tintColor); softwareBitmap.NormalBlend(tint); using (InMemoryRandomAccessStream memory = new()) diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs index 7e38f42e..917d1284 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs @@ -51,18 +51,11 @@ internal class DailyNoteViewModel : Abstraction.ViewModel /// 构造一个新的实时便笺视图模型 /// /// 服务提供器 - /// 用户服务 - /// 实时便笺服务 - /// 数据库上下文 - public DailyNoteViewModel( - IServiceProvider serviceProvider, - IUserService userService, - IDailyNoteService dailyNoteService, - AppDbContext appDbContext) + public DailyNoteViewModel(IServiceProvider serviceProvider) { - this.userService = userService; - this.dailyNoteService = dailyNoteService; - this.appDbContext = appDbContext; + userService = serviceProvider.GetRequiredService(); + dailyNoteService = serviceProvider.GetRequiredService(); + appDbContext = serviceProvider.GetRequiredService(); this.serviceProvider = serviceProvider; OpenUICommand = new AsyncRelayCommand(OpenUIAsync); @@ -92,7 +85,7 @@ internal class DailyNoteViewModel : Abstraction.ViewModel { if (!ScheduleTaskHelper.RegisterForDailyNoteRefresh(value.Value)) { - Ioc.Default.GetRequiredService().Warning(SH.ViewModelDailyNoteRegisterTaskFail); + serviceProvider.GetRequiredService().Warning(SH.ViewModelDailyNoteRegisterTaskFail); } else { @@ -244,10 +237,13 @@ internal class DailyNoteViewModel : Abstraction.ViewModel { if (entry != null) { - // ContentDialog must be created by main thread. - await ThreadHelper.SwitchToMainThreadAsync(); - await new DailyNoteNotificationDialog(entry).ShowAsync(); - appDbContext.DailyNotes.UpdateAndSave(entry); + using (await EnterCriticalExecutionAsync().ConfigureAwait(false)) + { + // ContentDialog must be created by main thread. + await ThreadHelper.SwitchToMainThreadAsync(); + await new DailyNoteNotificationDialog(entry).ShowAsync(); + appDbContext.DailyNotes.UpdateAndSave(entry); + } } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs index 66ef9772..b95352a7 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs @@ -18,11 +18,16 @@ namespace Snap.Hutao.ViewModel; [Injection(InjectAs.Scoped)] internal class ExperimentalFeaturesViewModel : ObservableObject { + private readonly IServiceProvider serviceProvider; + /// /// 构造一个新的实验性功能视图模型 /// - public ExperimentalFeaturesViewModel() + /// 服务提供器 + public ExperimentalFeaturesViewModel(IServiceProvider serviceProvider) { + this.serviceProvider = serviceProvider; + OpenCacheFolderCommand = new AsyncRelayCommand(OpenCacheFolderAsync); OpenDataFolderCommand = new AsyncRelayCommand(OpenDataFolderAsync); DeleteUsersCommand = new AsyncRelayCommand(DangerousDeleteUsersAsync); @@ -61,7 +66,7 @@ internal class ExperimentalFeaturesViewModel : ObservableObject private async Task DangerousDeleteUsersAsync() { - using (IServiceScope scope = Ioc.Default.CreateScope()) + using (IServiceScope scope = serviceProvider.CreateScope()) { AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService(); await appDbContext.Users.ExecuteDeleteAsync().ConfigureAwait(false); @@ -73,7 +78,7 @@ internal class ExperimentalFeaturesViewModel : ObservableObject private void DangerousDeleteAllScheduleTasks() { - IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); + IInfoBarService infoBarService = serviceProvider.GetRequiredService(); if (Core.ScheduleTaskHelper.UnregisterAllTasks()) { infoBarService.Success(SH.ViewModelExperimentalDeleteTaskSuccess); diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLogViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLogViewModel.cs index 34e0f867..a55b7919 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLogViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLogViewModel.cs @@ -150,11 +150,8 @@ internal class GachaLogViewModel : Abstraction.ViewModel if (await gachaLogService.InitializeAsync(CancellationToken).ConfigureAwait(true)) { ObservableCollection archives; - - ThrowIfViewDisposed(); - using (await DisposeLock.EnterAsync().ConfigureAwait(false)) + using (await EnterCriticalExecutionAsync().ConfigureAwait(false)) { - ThrowIfViewDisposed(); archives = await gachaLogService.GetArchiveCollectionAsync().ConfigureAwait(false); } @@ -204,13 +201,13 @@ internal class GachaLogViewModel : Abstraction.ViewModel try { - using (await DisposeLock.EnterAsync().ConfigureAwait(false)) + using (await EnterCriticalExecutionAsync().ConfigureAwait(false)) { try { authkeyValid = await gachaLogService.RefreshGachaLogAsync(query, strategy, progress, CancellationToken).ConfigureAwait(false); } - catch (Core.ExceptionService.UserdataCorruptedException ex) + catch (UserdataCorruptedException ex) { authkeyValid = false; infoBarService.Error(ex); @@ -304,11 +301,14 @@ internal class GachaLogViewModel : Abstraction.ViewModel if (result == ContentDialogResult.Primary) { - await gachaLogService.RemoveArchiveAsync(SelectedArchive).ConfigureAwait(false); + using (await EnterCriticalExecutionAsync().ConfigureAwait(false)) + { + await gachaLogService.RemoveArchiveAsync(SelectedArchive).ConfigureAwait(false); - // reselect first archive - await ThreadHelper.SwitchToMainThreadAsync(); - SelectedArchive = Archives.FirstOrDefault(); + // reselect first archive + await ThreadHelper.SwitchToMainThreadAsync(); + SelectedArchive = Archives.FirstOrDefault(); + } } } } @@ -354,7 +354,7 @@ internal class GachaLogViewModel : Abstraction.ViewModel } catch (UserdataCorruptedException ex) { - Ioc.Default.GetRequiredService().Error(ex); + infoBarService.Error(ex); } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoDatabaseViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoDatabaseViewModel.cs index e78a0e90..8212a8a9 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoDatabaseViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoDatabaseViewModel.cs @@ -2,15 +2,9 @@ // Licensed under the MIT license. using CommunityToolkit.Mvvm.Input; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Media.Imaging; using Snap.Hutao.Model.Binding.Hutao; using Snap.Hutao.Service.Hutao; using Snap.Hutao.Web.Hutao.Model; -using System.IO; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Graphics.Imaging; -using Windows.Storage.Streams; namespace Snap.Hutao.ViewModel; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/LaunchGameViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/LaunchGameViewModel.cs index 874a6359..4a48519b 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/LaunchGameViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/LaunchGameViewModel.cs @@ -4,6 +4,7 @@ using CommunityToolkit.Mvvm.Input; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; using Snap.Hutao.Control.Extension; using Snap.Hutao.Core.Database; using Snap.Hutao.Core.LifeCycle; @@ -12,7 +13,6 @@ using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity.Database; using Snap.Hutao.Service.Abstraction; using Snap.Hutao.Service.Game; -using Snap.Hutao.Service.Game.Unlocker; using Snap.Hutao.Service.Navigation; using Snap.Hutao.Service.User; using Snap.Hutao.View.Dialog; @@ -36,6 +36,7 @@ internal class LaunchGameViewModel : Abstraction.ViewModel private static readonly string TrueString = true.ToString(); private static readonly string FalseString = false.ToString(); + private readonly IServiceProvider serviceProvider; private readonly IGameService gameService; private readonly AppDbContext appDbContext; private readonly IMemoryCache memoryCache; @@ -56,17 +57,13 @@ internal class LaunchGameViewModel : Abstraction.ViewModel /// /// 构造一个新的启动游戏视图模型 /// - /// 游戏服务 - /// 内存缓存 - /// 数据库上下文 - public LaunchGameViewModel( - IGameService gameService, - IMemoryCache memoryCache, - AppDbContext appDbContext) + /// 服务提供器 + public LaunchGameViewModel(IServiceProvider serviceProvider) { - this.gameService = gameService; - this.appDbContext = appDbContext; - this.memoryCache = memoryCache; + gameService = serviceProvider.GetRequiredService(); + appDbContext = serviceProvider.GetRequiredService(); + memoryCache = serviceProvider.GetRequiredService(); + this.serviceProvider = serviceProvider; OpenUICommand = new AsyncRelayCommand(OpenUIAsync); LaunchCommand = new AsyncRelayCommand(LaunchAsync); @@ -210,11 +207,8 @@ internal class LaunchGameViewModel : Abstraction.ViewModel { try { - ThrowIfViewDisposed(); - using (await DisposeLock.EnterAsync(CancellationToken).ConfigureAwait(true)) + using (await EnterCriticalExecutionAsync().ConfigureAwait(false)) { - ThrowIfViewDisposed(); - MultiChannel multi = gameService.GetMultiChannel(); if (string.IsNullOrEmpty(multi.ConfigFilePath)) { @@ -222,7 +216,7 @@ internal class LaunchGameViewModel : Abstraction.ViewModel } else { - Ioc.Default.GetRequiredService().Warning(SH.ViewModelLaunchGameMultiChannelReadFail); + serviceProvider.GetRequiredService().Warning(SH.ViewModelLaunchGameMultiChannelReadFail); } GameAccounts = await gameService.GetGameAccountCollectionAsync().ConfigureAwait(true); @@ -231,6 +225,7 @@ internal class LaunchGameViewModel : Abstraction.ViewModel if (memoryCache.TryGetValue(DesiredUid, out object? value) && value is string uid) { SelectedGameAccount = GameAccounts.FirstOrDefault(g => g.AttachUid == uid); + memoryCache.Remove(DesiredUid); } // Sync from Settings @@ -243,8 +238,8 @@ internal class LaunchGameViewModel : Abstraction.ViewModel } else { - Ioc.Default.GetRequiredService().Warning(SH.ViewModelLaunchGamePathInvalid); - await Ioc.Default.GetRequiredService() + serviceProvider.GetRequiredService().Warning(SH.ViewModelLaunchGamePathInvalid); + await serviceProvider.GetRequiredService() .NavigateAsync(INavigationAwaiter.Default, true) .ConfigureAwait(false); } @@ -288,7 +283,7 @@ internal class LaunchGameViewModel : Abstraction.ViewModel private async Task LaunchAsync() { - IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); + IInfoBarService infoBarService = serviceProvider.GetRequiredService(); if (gameService.IsGameRunning()) { @@ -344,7 +339,7 @@ internal class LaunchGameViewModel : Abstraction.ViewModel } catch (Core.ExceptionService.UserdataCorruptedException ex) { - Ioc.Default.GetRequiredService().Error(ex); + serviceProvider.GetRequiredService().Error(ex); } } @@ -352,8 +347,8 @@ internal class LaunchGameViewModel : Abstraction.ViewModel { if (gameAccount != null) { - IUserService userService = Ioc.Default.GetRequiredService(); - IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); + IUserService userService = serviceProvider.GetRequiredService(); + IInfoBarService infoBarService = serviceProvider.GetRequiredService(); if (userService.Current?.SelectedUserGameRole is UserGameRole role) { diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs index 13f66030..64ba4295 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs @@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; +using Microsoft.Extensions.DependencyInjection; using Snap.Hutao.Core.Database; using Snap.Hutao.Core.IO; using Snap.Hutao.Core.Setting; @@ -27,6 +28,7 @@ namespace Snap.Hutao.ViewModel; [Injection(InjectAs.Scoped)] internal class SettingViewModel : Abstraction.ViewModel { + private readonly IServiceProvider serviceProvider; private readonly AppDbContext appDbContext; private readonly IGameService gameService; private readonly ILogger logger; @@ -46,21 +48,14 @@ internal class SettingViewModel : Abstraction.ViewModel /// /// 构造一个新的设置视图模型 /// - /// 数据库上下文 - /// 游戏服务 - /// 实验性功能 - /// 日志器 - public SettingViewModel( - AppDbContext appDbContext, - IGameService gameService, - ExperimentalFeaturesViewModel experimental, - ILogger logger) + /// 服务提供器 + public SettingViewModel(IServiceProvider serviceProvider) { - this.appDbContext = appDbContext; - this.gameService = gameService; - this.logger = logger; - - Experimental = experimental; + appDbContext = serviceProvider.GetRequiredService(); + gameService = serviceProvider.GetRequiredService(); + logger = serviceProvider.GetRequiredService>(); + Experimental = serviceProvider.GetRequiredService(); + this.serviceProvider = serviceProvider; isEmptyHistoryWishVisibleEntry = appDbContext.Settings.SingleOrAdd(SettingEntry.IsEmptyHistoryWishVisible, SettingEntryHelper.TrueString); IsEmptyHistoryWishVisible = bool.Parse(isEmptyHistoryWishVisibleEntry.Value!); @@ -152,7 +147,7 @@ internal class SettingViewModel : Abstraction.ViewModel { selectedBackdropTypeEntry.Value = value.Value.ToString(); appDbContext.Settings.UpdateAndSave(selectedBackdropTypeEntry); - Ioc.Default.GetRequiredService().Send(new Message.BackdropTypeChangedMessage(value.Value)); + serviceProvider.GetRequiredService().Send(new Message.BackdropTypeChangedMessage(value.Value)); } } } @@ -189,7 +184,7 @@ internal class SettingViewModel : Abstraction.ViewModel private async Task SetGamePathAsync() { - IGameLocator locator = Ioc.Default.GetRequiredService>() + IGameLocator locator = serviceProvider.GetRequiredService>() .Single(l => l.Name == nameof(ManualGameLocator)); (bool isOk, string path) = await locator.LocateGamePathAsync().ConfigureAwait(false); @@ -203,7 +198,7 @@ internal class SettingViewModel : Abstraction.ViewModel private void DeleteGameWebCache() { - IGameService gameService = Ioc.Default.GetRequiredService(); + IGameService gameService = serviceProvider.GetRequiredService(); string gamePath = gameService.GetGamePathSkipLocator(); if (!string.IsNullOrEmpty(gamePath)) @@ -211,7 +206,7 @@ internal class SettingViewModel : Abstraction.ViewModel string cacheFilePath = GachaLogQueryWebCacheProvider.GetCacheFile(gamePath); string cacheFolder = Path.GetDirectoryName(cacheFilePath)!; - IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); + IInfoBarService infoBarService = serviceProvider.GetRequiredService(); if (Directory.Exists(cacheFolder)) { try @@ -243,7 +238,7 @@ internal class SettingViewModel : Abstraction.ViewModel private async Task CheckUpdateAsync() { #if DEBUG - await Ioc.Default + await serviceProvider .GetRequiredService() .NavigateAsync(Service.Navigation.INavigationAwaiter.Default) .ConfigureAwait(false); @@ -254,11 +249,11 @@ internal class SettingViewModel : Abstraction.ViewModel private async Task SetDataFolderAsync() { - IPickerFactory pickerFactory = Ioc.Default.GetRequiredService(); + IPickerFactory pickerFactory = serviceProvider.GetRequiredService(); FolderPicker picker = pickerFactory.GetFolderPicker(); (bool isOk, string folder) = await picker.TryPickSingleFolderAsync().ConfigureAwait(false); - IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); + IInfoBarService infoBarService = serviceProvider.GetRequiredService(); if (isOk) { LocalSetting.Set(SettingKeys.DataFolderPath, folder); diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyssRecordViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyssRecordViewModel.cs index 68d59bea..9299eb30 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyssRecordViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyssRecordViewModel.cs @@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; +using Microsoft.Extensions.DependencyInjection; using Snap.Hutao.Message; using Snap.Hutao.Model.Binding.SpiralAbyss; using Snap.Hutao.Model.Binding.User; @@ -25,6 +26,7 @@ namespace Snap.Hutao.ViewModel; [Injection(InjectAs.Scoped)] internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient { + private readonly IServiceProvider serviceProvider; private readonly ISpiralAbyssRecordService spiralAbyssRecordService; private readonly IMetadataService metadataService; private readonly IUserService userService; @@ -37,25 +39,23 @@ internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient /// 构造一个新的深渊记录视图模型 /// + /// 服务提供器 /// 深渊记录服务 /// 元数据服务 /// 用户服务 /// 消息器 - public SpiralAbyssRecordViewModel( - ISpiralAbyssRecordService spiralAbyssRecordService, - IMetadataService metadataService, - IUserService userService, - IMessenger messenger) + public SpiralAbyssRecordViewModel(IServiceProvider serviceProvider) { - this.spiralAbyssRecordService = spiralAbyssRecordService; - this.metadataService = metadataService; - this.userService = userService; + spiralAbyssRecordService = serviceProvider.GetRequiredService(); + metadataService = serviceProvider.GetRequiredService(); + userService = serviceProvider.GetRequiredService(); + this.serviceProvider = serviceProvider; OpenUICommand = new AsyncRelayCommand(OpenUIAsync); RefreshCommand = new AsyncRelayCommand(RefreshAsync); UploadSpiralAbyssRecordCommand = new AsyncRelayCommand(UploadSpiralAbyssRecordAsync); - messenger.Register(this); + serviceProvider.GetRequiredService().Register(this); } /// @@ -123,10 +123,12 @@ internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient().Warning(SH.MustSelectUserAndUid); + serviceProvider.GetRequiredService().Warning(SH.MustSelectUserAndUid); } } } @@ -136,10 +138,8 @@ internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient? temp = null; try { - ThrowIfViewDisposed(); - using (await DisposeLock.EnterAsync().ConfigureAwait(false)) + using (await EnterCriticalExecutionAsync().ConfigureAwait(false)) { - ThrowIfViewDisposed(); temp = await spiralAbyssRecordService .GetSpiralAbyssCollectionAsync(userAndUid) .ConfigureAwait(false); @@ -156,16 +156,14 @@ internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient(); - IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); + HomaClient homaClient = serviceProvider.GetRequiredService(); + IInfoBarService infoBarService = serviceProvider.GetRequiredService(); if (UserAndUid.TryFromUser(userService.Current, out UserAndUid? userAndUid)) { diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/TestViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/TestViewModel.cs index c19b1385..9e83d848 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/TestViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/TestViewModel.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using CommunityToolkit.Mvvm.Input; +using Microsoft.Extensions.DependencyInjection; using Snap.Hutao.Core.IO; using Snap.Hutao.Core.IO.Bits; using Snap.Hutao.Service.User; @@ -18,11 +19,16 @@ namespace Snap.Hutao.ViewModel; [Injection(InjectAs.Scoped)] internal class TestViewModel : Abstraction.ViewModel { + private readonly IServiceProvider serviceProvider; + /// /// 构造一个新的测试视图模型 /// - public TestViewModel() + /// 服务提供器 + public TestViewModel(IServiceProvider serviceProvider) { + this.serviceProvider = serviceProvider; + ShowCommunityGameRecordDialogCommand = new AsyncRelayCommand(ShowCommunityGameRecordDialogAsync); ShowAdoptCalculatorDialogCommand = new AsyncRelayCommand(ShowAdoptCalculatorDialogAsync); DangerousLoginMihoyoBbsCommand = new AsyncRelayCommand(DangerousLoginMihoyoBbsAsync); @@ -71,7 +77,7 @@ internal class TestViewModel : Abstraction.ViewModel if (isOk) { - (Response? resp, Aigis? aigis) = await Ioc.Default + (Response? resp, Aigis? aigis) = await serviceProvider .GetRequiredService() .LoginByPasswordAsync(data, CancellationToken.None) .ConfigureAwait(false); @@ -82,7 +88,7 @@ internal class TestViewModel : Abstraction.ViewModel { Cookie cookie = Cookie.FromLoginResult(resp.Data); - await Ioc.Default + await serviceProvider .GetRequiredService() .ProcessInputCookieAsync(cookie) .ConfigureAwait(false); @@ -97,9 +103,9 @@ internal class TestViewModel : Abstraction.ViewModel private async Task DownloadStaticFileAsync() { - BitsManager bitsManager = Ioc.Default.GetRequiredService(); + BitsManager bitsManager = serviceProvider.GetRequiredService(); Uri testUri = new(Web.HutaoEndpoints.StaticZip("AvatarIcon")); - ILogger logger = Ioc.Default.GetRequiredService>(); + ILogger logger = serviceProvider.GetRequiredService>(); Progress progress = new(status => logger.LogInformation("{info}", status)); (bool isOk, TempFile file) = await bitsManager.DownloadAsync(testUri, progress).ConfigureAwait(false); diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/UserViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/UserViewModel.cs index 2cea4ea9..32334aad 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/UserViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/UserViewModel.cs @@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using Microsoft.Extensions.DependencyInjection; using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Core.IO.DataTransfer; using Snap.Hutao.Extension; @@ -24,6 +25,7 @@ namespace Snap.Hutao.ViewModel; [Injection(InjectAs.Singleton)] internal class UserViewModel : ObservableObject { + private readonly IServiceProvider serviceProvider; private readonly IUserService userService; private readonly IInfoBarService infoBarService; @@ -33,12 +35,14 @@ internal class UserViewModel : ObservableObject /// /// 构造一个新的用户视图模型 /// + /// 服务提供器 /// 用户服务 /// 信息条服务 - public UserViewModel(IUserService userService, IInfoBarService infoBarService) + public UserViewModel(IServiceProvider serviceProvider) { - this.userService = userService; - this.infoBarService = infoBarService; + userService = serviceProvider.GetRequiredService(); + infoBarService = serviceProvider.GetRequiredService(); + this.serviceProvider = serviceProvider; OpenUICommand = new AsyncRelayCommand(OpenUIAsync); AddUserCommand = new AsyncRelayCommand(AddUserAsync); @@ -155,7 +159,7 @@ internal class UserViewModel : ObservableObject { if (Core.WebView2Helper.IsSupported) { - Ioc.Default.GetRequiredService().Navigate(INavigationAwaiter.Default); + serviceProvider.GetRequiredService().Navigate(INavigationAwaiter.Default); } else { diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs index 4ad59de3..c8bd97e8 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs @@ -207,15 +207,22 @@ internal class WelcomeViewModel : ObservableObject private void ExtractFiles(string file) { IImageCacheFilePathOperation imageCache = serviceProvider.GetRequiredService().ImplictAs()!; - - using (ZipArchive archive = ZipFile.OpenRead(file)) + try { - foreach (ZipArchiveEntry entry in archive.Entries) + using (ZipArchive archive = ZipFile.OpenRead(file)) { - string destPath = imageCache.GetFilePathFromCategoryAndFileName(fileName, entry.FullName); - entry.ExtractToFile(destPath, true); + foreach (ZipArchiveEntry entry in archive.Entries) + { + string destPath = imageCache.GetFilePathFromCategoryAndFileName(fileName, entry.FullName); + entry.ExtractToFile(destPath, true); + } } } + catch (InvalidDataException) + { + // System.IO.InvalidDataException: End of Central Directory record could not be found. + // Basically the file downloaded is corrupted, skip anyway. + } } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs index 1f84f485..2d47748c 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs @@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.Input; using CommunityToolkit.WinUI.UI; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Primitives; using Snap.Hutao.Extension; using Snap.Hutao.Model.Binding.Cultivation; @@ -34,6 +35,7 @@ namespace Snap.Hutao.ViewModel; [Injection(InjectAs.Scoped)] internal class WikiAvatarViewModel : Abstraction.ViewModel { + private readonly IServiceProvider serviceProvider; private readonly IMetadataService metadataService; private readonly IHutaoCache hutaoCache; @@ -44,12 +46,13 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel /// /// 构造一个新的角色资料视图模型 /// - /// 元数据服务 - /// 胡桃缓存 - public WikiAvatarViewModel(IMetadataService metadataService, IHutaoCache hutaoCache) + /// 服务提供器 + public WikiAvatarViewModel(IServiceProvider serviceProvider) { - this.metadataService = metadataService; - this.hutaoCache = hutaoCache; + metadataService = serviceProvider.GetRequiredService(); + hutaoCache = serviceProvider.GetRequiredService(); + this.serviceProvider = serviceProvider; + OpenUICommand = new AsyncRelayCommand(OpenUIAsync); CultivateCommand = new AsyncRelayCommand(CultivateAsync); FilterCommand = new RelayCommand(ApplyFilter); @@ -123,8 +126,8 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel { if (avatar != null) { - IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); - IUserService userService = Ioc.Default.GetRequiredService(); + IInfoBarService infoBarService = serviceProvider.GetRequiredService(); + IUserService userService = serviceProvider.GetRequiredService(); if (userService.Current != null) { @@ -136,7 +139,7 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel if (isOk) { - Response consumptionResponse = await Ioc.Default + Response consumptionResponse = await serviceProvider .GetRequiredService() .ComputeAsync(userService.Current.Entity, delta) .ConfigureAwait(false); @@ -146,18 +149,25 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel CalcConsumption consumption = consumptionResponse.Data; List items = CalcItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume); - bool saved = await Ioc.Default - .GetRequiredService() - .SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, items) - .ConfigureAwait(false); + try + { + bool saved = await serviceProvider + .GetRequiredService() + .SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, items) + .ConfigureAwait(false); - if (saved) - { - infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess); + if (saved) + { + infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess); + } + else + { + infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning); + } } - else + catch (Core.ExceptionService.UserdataCorruptedException ex) { - infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning); + infoBarService.Error(ex, SH.ViewModelCultivationAddWarning); } } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs index a6fa4f2c..982c66f0 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs @@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.Input; using CommunityToolkit.WinUI.UI; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Primitives; using Snap.Hutao.Extension; using Snap.Hutao.Model.Binding.Cultivation; @@ -37,6 +38,7 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel 11419, 11420, 11421, // 「一心传」名刀 }; + private readonly IServiceProvider serviceProvider; private readonly IMetadataService metadataService; private readonly IHutaoCache hutaoCache; @@ -47,12 +49,12 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel /// /// 构造一个新的武器资料视图模型 /// - /// 元数据服务 - /// 胡桃缓存 - public WikiWeaponViewModel(IMetadataService metadataService, IHutaoCache hutaoCache) + /// 服务提供器 + public WikiWeaponViewModel(IServiceProvider serviceProvider) { - this.metadataService = metadataService; - this.hutaoCache = hutaoCache; + metadataService = serviceProvider.GetRequiredService(); + hutaoCache = serviceProvider.GetRequiredService(); + this.serviceProvider = serviceProvider; OpenUICommand = new AsyncRelayCommand(OpenUIAsync); CultivateCommand = new AsyncRelayCommand(CultivateAsync); @@ -122,8 +124,8 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel { if (weapon != null) { - IInfoBarService infoBarService = Ioc.Default.GetRequiredService(); - IUserService userService = Ioc.Default.GetRequiredService(); + IInfoBarService infoBarService = serviceProvider.GetRequiredService(); + IUserService userService = serviceProvider.GetRequiredService(); if (userService.Current != null) { @@ -135,7 +137,7 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel if (isOk) { - Response consumptionResponse = await Ioc.Default + Response consumptionResponse = await serviceProvider .GetRequiredService() .ComputeAsync(userService.Current.Entity, delta) .ConfigureAwait(false); @@ -144,18 +146,25 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel { CalcConsumption consumption = consumptionResponse.Data; - bool saved = await Ioc.Default - .GetRequiredService() - .SaveConsumptionAsync(CultivateType.Weapon, weapon.Id, consumption.WeaponConsume.EmptyIfNull()) - .ConfigureAwait(false); + try + { + bool saved = await serviceProvider + .GetRequiredService() + .SaveConsumptionAsync(CultivateType.Weapon, weapon.Id, consumption.WeaponConsume.EmptyIfNull()) + .ConfigureAwait(false); - if (saved) - { - infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess); + if (saved) + { + infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess); + } + else + { + infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning); + } } - else + catch (Core.ExceptionService.UserdataCorruptedException ex) { - infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning); + infoBarService.Error(ex, SH.ViewModelCultivationAddWarning); } } } diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/DynamicSecret/DynamicSecretHandler.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/DynamicSecret/DynamicSecretHandler.cs index 5351d6a1..9fd7a1cc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/DynamicSecret/DynamicSecretHandler.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/DynamicSecret/DynamicSecretHandler.cs @@ -3,7 +3,6 @@ using Snap.Hutao.Web.Request; using System.Net.Http; -using System.Text; namespace Snap.Hutao.Web.Hoyolab.DynamicSecret; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/HttpClientExtensions.cs b/src/Snap.Hutao/Snap.Hutao/Web/HttpClientExtensions.cs index 8c9e1031..61aecb37 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/HttpClientExtensions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/HttpClientExtensions.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. using Snap.Hutao.Core.Logging; -using Snap.Hutao.Extension; using System.IO; using System.Net.Http; using System.Net.Http.Json;