From 9ef48ab05ceab74d90e2e83895f0fbabc269cdec Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Wed, 11 Jan 2023 16:02:14 +0800 Subject: [PATCH] fix crashes --- .../ExceptionService/ExceptionRecorder.cs | 5 ++- .../Factory/AsyncRelayCommandFactory.cs | 1 - .../Snap.Hutao/Model/Metadata/Material.cs | 34 +++++++++++++++++++ .../Service/AvatarInfo/AvatarInfoService.cs | 18 ++++++---- .../Service/Cultivation/CultivationService.cs | 34 ++----------------- .../Service/Game/Locator/ManualGameLocator.cs | 1 - .../Snap.Hutao/View/Page/CultivationPage.xaml | 2 +- .../ViewModel/AchievementViewModel.cs | 2 +- .../ViewModel/AvatarPropertyViewModel.cs | 1 + .../ViewModel/CultivationViewModel.cs | 13 +++++-- .../Common/Announcement/AnnouncementClient.cs | 1 - .../Hoyolab/HoyolabHttpClientExtensions.cs | 7 +++- .../Hoyolab/Takumi/Binding/BindingClient.cs | 1 - .../Takumi/GameRecord/GameRecordClient.cs | 1 - .../Snap.Hutao/Web/Hutao/HomaClient.cs | 1 - .../Snap.Hutao/Win32/StructMarshal.cs | 1 - 16 files changed, 69 insertions(+), 54 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionRecorder.cs b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionRecorder.cs index 59a73b83..7c3d6d76 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionRecorder.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionRecorder.cs @@ -3,7 +3,6 @@ using Microsoft.UI.Xaml; using Snap.Hutao.Core.Logging; -using Snap.Hutao.Web.Hutao; namespace Snap.Hutao.Core.ExceptionService; @@ -30,9 +29,9 @@ internal class ExceptionRecorder private void OnAppUnhandledException(object? sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) { #if RELEASE - #pragma warning disable VSTHRD002 +#pragma warning disable VSTHRD002 Ioc.Default.GetRequiredService().UploadLogAsync(e.Exception).GetAwaiter().GetResult(); - #pragma warning restore VSTHRD002 +#pragma warning restore VSTHRD002 #endif logger.LogError(EventIds.UnhandledException, e.Exception, "未经处理的异常"); diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/AsyncRelayCommandFactory.cs b/src/Snap.Hutao/Snap.Hutao/Factory/AsyncRelayCommandFactory.cs index 84006d72..45c0c591 100644 --- a/src/Snap.Hutao/Snap.Hutao/Factory/AsyncRelayCommandFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Factory/AsyncRelayCommandFactory.cs @@ -4,7 +4,6 @@ using CommunityToolkit.Mvvm.Input; using Snap.Hutao.Core.Logging; using Snap.Hutao.Factory.Abstraction; -using Snap.Hutao.Web.Hutao; namespace Snap.Hutao.Factory; diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Material.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Material.cs index e580002b..5879ebae 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Material.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Material.cs @@ -55,4 +55,38 @@ public class Material /// 效果描述 /// public string? EffectDescription { get; set; } + + /// + /// 判断是否为物品栏物品 + /// + /// 是否为物品栏物品 + public bool IsInventoryItem() + { + // 原质 + if (Id == 112001) + { + return false; + } + + // 摩拉 + if (Id == 202) + { + return true; + } + + if (TypeDescription.EndsWith("区域特产")) + { + return true; + } + + return TypeDescription switch + { + "角色经验素材" => true, + "角色培养素材" => true, + "天赋培养素材" => true, + "武器强化素材" => true, + "武器突破素材" => true, + _ => false, + }; + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoService.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoService.cs index ac9c3324..151c0d32 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/AvatarInfoService.cs @@ -76,7 +76,7 @@ internal class AvatarInfoService : IAvatarInfoService if (resp.IsValid) { - IList list = UpdateDbAvatarInfos(userAndUid.Uid.Value, resp.AvatarInfoList); + IList list = UpdateDbAvatarInfos(userAndUid.Uid.Value, resp.AvatarInfoList, token); Summary summary = await GetSummaryCoreAsync(resp.PlayerInfo, list, token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); return new(RefreshResult.Ok, summary); @@ -90,7 +90,7 @@ internal class AvatarInfoService : IAvatarInfoService case RefreshOption.RequestFromHoyolabGameRecord: { EnkaPlayerInfo info = EnkaPlayerInfo.CreateEmpty(userAndUid.Uid.Value); - IList list = await UpdateDbAvatarInfosByGameRecordCharacterAsync(userAndUid).ConfigureAwait(false); + IList list = await UpdateDbAvatarInfosByGameRecordCharacterAsync(userAndUid, token).ConfigureAwait(false); Summary summary = await GetSummaryCoreAsync(info, list, token).ConfigureAwait(false); return new(RefreshResult.Ok, summary); } @@ -98,7 +98,7 @@ internal class AvatarInfoService : IAvatarInfoService case RefreshOption.RequestFromHoyolabCalculate: { EnkaPlayerInfo info = EnkaPlayerInfo.CreateEmpty(userAndUid.Uid.Value); - IList list = await UpdateDbAvatarInfosByCalculateAvatarDetailAsync(userAndUid).ConfigureAwait(false); + IList list = await UpdateDbAvatarInfosByCalculateAvatarDetailAsync(userAndUid, token).ConfigureAwait(false); Summary summary = await GetSummaryCoreAsync(info, list, token).ConfigureAwait(false); return new(RefreshResult.Ok, summary); } @@ -135,8 +135,9 @@ internal class AvatarInfoService : IAvatarInfoService return summary; } - private List UpdateDbAvatarInfos(string uid, IEnumerable webInfos) + private List UpdateDbAvatarInfos(string uid, IEnumerable webInfos, CancellationToken token) { + token.ThrowIfCancellationRequested(); List dbInfos = appDbContext.AvatarInfos .Where(i => i.Uid == uid) .ToList(); @@ -148,8 +149,10 @@ internal class AvatarInfoService : IAvatarInfoService continue; } - ModelAvatarInfo? entity = dbInfos.SingleOrDefault(i => i.Info.AvatarId == webInfo.AvatarId); + token.ThrowIfCancellationRequested(); + // TODO: ensure the operation executes atomically + ModelAvatarInfo? entity = dbInfos.SingleOrDefault(i => i.Info.AvatarId == webInfo.AvatarId); if (entity == null) { entity = ModelAvatarInfo.Create(uid, webInfo); @@ -162,10 +165,11 @@ internal class AvatarInfoService : IAvatarInfoService } } + token.ThrowIfCancellationRequested(); return GetDbAvatarInfos(uid); } - private async Task> UpdateDbAvatarInfosByGameRecordCharacterAsync(UserAndUid userAndUid) + private async Task> UpdateDbAvatarInfosByGameRecordCharacterAsync(UserAndUid userAndUid, CancellationToken token) { string uid = userAndUid.Uid.Value; List dbInfos = appDbContext.AvatarInfos @@ -218,7 +222,7 @@ internal class AvatarInfoService : IAvatarInfoService return GetDbAvatarInfos(uid); } - private async Task> UpdateDbAvatarInfosByCalculateAvatarDetailAsync(UserAndUid userAndUid) + private async Task> UpdateDbAvatarInfosByCalculateAvatarDetailAsync(UserAndUid userAndUid, CancellationToken token) { string uid = userAndUid.Uid.Value; List dbInfos = appDbContext.AvatarInfos diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs index 6a004b93..6b0b4e90 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs @@ -118,7 +118,7 @@ internal class CultivationService : ICultivationService .ToList(); List results = new(); - foreach (Model.Metadata.Material meta in metadata.Where(IsInventoryItem).OrderBy(m => m.Id)) + foreach (Model.Metadata.Material meta in metadata.Where(m => m.IsInventoryItem()).OrderBy(m => m.Id)) { InventoryItem entity = entities.SingleOrDefault(e => e.ItemId == meta.Id) ?? InventoryItem.Create(projectId, meta.Id); results.Add(new(meta, entity)); @@ -309,34 +309,4 @@ internal class CultivationService : ICultivationService return true; } - - private bool IsInventoryItem(Model.Metadata.Material material) - { - // 原质 - if (material.Id == 112001) - { - return false; - } - - // 摩拉 - if (material.Id == 202) - { - return true; - } - - if (material.TypeDescription.EndsWith("区域特产")) - { - return true; - } - - return material.TypeDescription switch - { - "角色经验素材" => true, - "角色培养素材" => true, - "天赋培养素材" => true, - "武器强化素材" => true, - "武器突破素材" => true, - _ => false, - }; - } -} +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Locator/ManualGameLocator.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Locator/ManualGameLocator.cs index 6f4dae0a..5bd33c0e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Locator/ManualGameLocator.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Locator/ManualGameLocator.cs @@ -3,7 +3,6 @@ using Snap.Hutao.Core.IO; using Snap.Hutao.Factory.Abstraction; -using Windows.Storage; using Windows.Storage.Pickers; namespace Snap.Hutao.Service.Game.Locator; diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml index 66be4c43..193ab960 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml @@ -42,7 +42,7 @@ - + /// 角色属性视图模型 +/// TODO: support page unload as cancellation /// [Injection(InjectAs.Scoped)] internal class AvatarPropertyViewModel : ObservableObject, ISupportCancellation diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/CultivationViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/CultivationViewModel.cs index bcf1af0d..cd3c3707 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/CultivationViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/CultivationViewModel.cs @@ -27,6 +27,7 @@ internal class CultivationViewModel : ObservableObject, ISupportCancellation private readonly IMetadataService metadataService; private readonly ILogger logger; + private bool isInitialized; private ObservableCollection? projects; private CultivateProject? selectedProject; private List? inventoryItems; @@ -65,6 +66,11 @@ internal class CultivationViewModel : ObservableObject, ISupportCancellation /// public CancellationToken CancellationToken { get; set; } + /// + /// 是否初始化完成 + /// + public bool IsInitialized { get => isInitialized; set => SetProperty(ref isInitialized, value); } + /// /// 项目 /// @@ -140,12 +146,15 @@ internal class CultivationViewModel : ObservableObject, ISupportCancellation private async Task OpenUIAsync() { - if (await metadataService.InitializeAsync().ConfigureAwait(true)) + bool metaInitialized = await metadataService.InitializeAsync().ConfigureAwait(true); + if (metaInitialized) { Projects = cultivationService.GetProjectCollection(); SelectedProject = cultivationService.Current; - await UpdateCultivateEntriesAndInventoryItemsAsync(SelectedProject).ConfigureAwait(false); + await UpdateCultivateEntriesAndInventoryItemsAsync(SelectedProject).ConfigureAwait(true); } + + IsInitialized = metaInitialized; } private async Task AddProjectAsync() diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/AnnouncementClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/AnnouncementClient.cs index 8458f186..032642c8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/AnnouncementClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/AnnouncementClient.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; -using Snap.Hutao.Extension; using Snap.Hutao.Web.Response; using System.Net.Http; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabHttpClientExtensions.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabHttpClientExtensions.cs index 1157eb88..9b29cb43 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabHttpClientExtensions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabHttpClientExtensions.cs @@ -40,7 +40,12 @@ internal static class HoyolabHttpClientExtensions stringBuilder.Append(user.Stoken).AppendIf(user.Stoken != null, ';'); } - httpClient.DefaultRequestHeaders.Set("Cookie", stringBuilder.ToString()); + string result = stringBuilder.ToString(); + if (!string.IsNullOrWhiteSpace(result)) + { + httpClient.DefaultRequestHeaders.Set("Cookie", result); + } + return httpClient; } diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient.cs index 9d6d0270..07737ea6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Binding/BindingClient.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; -using Snap.Hutao.Extension; using Snap.Hutao.Model.Entity; using Snap.Hutao.Web.Hoyolab.Annotation; using Snap.Hutao.Web.Response; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/GameRecordClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/GameRecordClient.cs index 5596927f..713157bd 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/GameRecordClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/GameRecord/GameRecordClient.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; -using Snap.Hutao.Extension; using Snap.Hutao.Model.Binding.User; using Snap.Hutao.Model.Primitive; using Snap.Hutao.Service.Abstraction; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaClient.cs index c5c83dda..42fa36bc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaClient.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; -using Snap.Hutao.Extension; using Snap.Hutao.Model.Binding.User; using Snap.Hutao.Web.Hoyolab; using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord; diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/StructMarshal.cs b/src/Snap.Hutao/Snap.Hutao/Win32/StructMarshal.cs index eeb2f027..bbf6332e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/StructMarshal.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/StructMarshal.cs @@ -1,7 +1,6 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Snap.Hutao.Web.Hoyolab; using System.Numerics; using Windows.Graphics; using Windows.Win32.System.Diagnostics.ToolHelp;