From 2c139a1ff69dc06c300def39250b29cfe23f0ce5 Mon Sep 17 00:00:00 2001
From: DismissedLight <1686188646@qq.com>
Date: Tue, 16 Jul 2024 14:48:21 +0800
Subject: [PATCH] cultivation save mode
---
.../Snap.Hutao/Resource/Localization/SH.resx | 21 +++
.../Service/Achievement/AchievementService.cs | 2 -
.../AvatarInfo/Factory/SummaryFactory.cs | 3 +-
.../Cultivation/ConsumptionSaveResultKind.cs | 12 ++
.../ConsumptionSaveStrategyKind.cs | 11 ++
.../Service/Cultivation/CultivationService.cs | 34 ++--
.../Cultivation/ICultivationService.cs | 30 +---
.../Service/Cultivation/InputConsumption.cs | 20 +++
.../Factory/GachaStatisticsFactory.cs | 4 +-
.../Game/Account/GameAccountService.cs | 10 +-
.../Game/Account/IGameAccountService.cs | 4 +-
.../Service/Game/GameServiceFacade.cs | 17 +-
.../Service/Game/IGameServiceFacade.cs | 4 +-
.../Service/User/UserInitializationService.cs | 3 +-
.../Layout/UniformStaggeredLayoutState.cs | 6 +-
.../UI/Xaml/Data/AdvancedCollectionView.cs | 1 -
.../View/Dialog/AchievementImportDialog.xaml | 2 +-
.../Dialog/AchievementImportDialog.xaml.cs | 13 --
.../CultivatePromotionDeltaBatchDialog.xaml | 9 +
...CultivatePromotionDeltaBatchDialog.xaml.cs | 7 +-
.../Dialog/CultivatePromotionDeltaDialog.xaml | 24 +--
.../CultivatePromotionDeltaDialog.xaml.cs | 20 +--
.../Dialog/CultivatePromotionDeltaOptions.cs | 20 +++
...dSelection.xaml.cs => UIGFUidSelection.cs} | 0
.../Achievement/AchievementViewModel.cs | 88 +++++-----
.../AvatarProperty/AvatarPropertyViewModel.cs | 161 +++++++++++-------
.../AvatarPropertyViewModelScopeContext.cs | 41 +++++
.../AvatarProperty/BatchCultivateResult.cs | 1 -
.../ViewModel/Game/LaunchGameViewModel.cs | 2 +-
.../ViewModel/Game/LaunchGameViewModelSlim.cs | 3 +-
.../Setting/SettingGachaLogViewModel.cs | 1 -
.../SpiralAbyss/SpiralAbyssRecordViewModel.cs | 2 +-
.../ViewModel/Wiki/WikiAvatarViewModel.cs | 48 ++++--
.../ViewModel/Wiki/WikiMonsterViewModel.cs | 2 +-
.../ViewModel/Wiki/WikiWeaponViewModel.cs | 48 ++++--
35 files changed, 416 insertions(+), 258 deletions(-)
create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ConsumptionSaveResultKind.cs
create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ConsumptionSaveStrategyKind.cs
create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Cultivation/InputConsumption.cs
create mode 100644 src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaOptions.cs
rename src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/{UIGFUidSelection.xaml.cs => UIGFUidSelection.cs} (100%)
create mode 100644 src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModelScopeContext.cs
diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
index 74061358..301bfb91 100644
--- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
+++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
@@ -1247,6 +1247,18 @@
添加或更新到当前养成计划
+
+ 总是创建新的养成目标物品
+
+
+ 保存方式
+
+
+ 覆盖存在的养成目标物品
+
+
+ 保留存在的养成目标物品
+
每日委托上线提醒
@@ -1598,6 +1610,15 @@
操作未全部完成:添加 / 更新:{0} 个,跳过 {1} 个
+
+ 选定的等级不需要养成材料
+
+
+ 尚未创建并选择养成计划
+
+
+ 已存在该物品的养成项目
+
已成功添加至当前养成计划
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs
index 2ccf0181..49e22838 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Achievement/AchievementService.cs
@@ -8,12 +8,10 @@ using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.InterChange.Achievement;
using Snap.Hutao.Model.Primitive;
using Snap.Hutao.ViewModel.Achievement;
-using System.Collections.ObjectModel;
using EntityAchievement = Snap.Hutao.Model.Entity.Achievement;
namespace Snap.Hutao.Service.Achievement;
-[HighQuality]
[ConstructorGenerated]
[Injection(InjectAs.Scoped, typeof(IAchievementService))]
internal sealed partial class AchievementService : IAchievementService
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactory.cs
index 02aa3da0..7141a443 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactory.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryFactory.cs
@@ -4,6 +4,7 @@
using Snap.Hutao.Model.Metadata;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Service.Metadata.ContextAbstraction;
+using Snap.Hutao.UI.Xaml.Data;
using Snap.Hutao.ViewModel.AvatarProperty;
namespace Snap.Hutao.Service.AvatarInfo.Factory;
@@ -38,7 +39,7 @@ internal sealed partial class SummaryFactory : ISummaryFactory
return new()
{
- Avatars = new(views),
+ Avatars = views.ToAdvancedCollectionView(),
};
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ConsumptionSaveResultKind.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ConsumptionSaveResultKind.cs
new file mode 100644
index 00000000..3244fa10
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ConsumptionSaveResultKind.cs
@@ -0,0 +1,12 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+namespace Snap.Hutao.Service.Cultivation;
+
+internal enum ConsumptionSaveResultKind
+{
+ NoItem,
+ NoProject,
+ Skipped,
+ Added,
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ConsumptionSaveStrategyKind.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ConsumptionSaveStrategyKind.cs
new file mode 100644
index 00000000..4f5de156
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ConsumptionSaveStrategyKind.cs
@@ -0,0 +1,11 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+namespace Snap.Hutao.Service.Cultivation;
+
+internal enum ConsumptionSaveStrategyKind
+{
+ PreserveExisting,
+ OverwriteExisting,
+ CreateNewEntry,
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs
index 10951cf2..f7587642 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationService.cs
@@ -8,7 +8,6 @@ using Snap.Hutao.Service.Inventory;
using Snap.Hutao.Service.Metadata.ContextAbstraction;
using Snap.Hutao.ViewModel.Cultivation;
using System.Collections.ObjectModel;
-using CalculateItem = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Item;
using ModelItem = Snap.Hutao.Model.Item;
namespace Snap.Hutao.Service.Cultivation;
@@ -115,45 +114,54 @@ internal sealed partial class CultivationService : ICultivationService
}
///
- public async ValueTask SaveConsumptionAsync(CultivateType type, uint itemId, List items, LevelInformation levelInformation)
+ public async ValueTask SaveConsumptionAsync(InputConsumption inputConsumption)
{
- if (items.Count == 0)
+ if (inputConsumption.Items.Count == 0)
{
- return true;
+ return ConsumptionSaveResultKind.NoItem;
}
- await taskContext.SwitchToMainThreadAsync();
if (Projects.CurrentItem is null)
{
+ await taskContext.SwitchToMainThreadAsync();
Projects.MoveCurrentTo(Projects.SourceCollection.SelectedOrDefault());
if (Projects.CurrentItem is null)
{
- return false;
+ return ConsumptionSaveResultKind.NoProject;
}
}
await taskContext.SwitchToBackgroundAsync();
- CultivateEntry? entry = type is CultivateType.AvatarAndSkill
- ? cultivationDbService.GetCultivateEntryByProjectIdAndItemId(Projects.CurrentItem.InnerId, itemId)
- : default;
+
+ CultivateEntry? entry = default;
+
+ if (inputConsumption.Strategy is ConsumptionSaveStrategyKind.PreserveExisting or ConsumptionSaveStrategyKind.OverwriteExisting)
+ {
+ entry = cultivationDbService.GetCultivateEntryByProjectIdAndItemId(Projects.CurrentItem.InnerId, inputConsumption.ItemId);
+
+ if (inputConsumption.Strategy is ConsumptionSaveStrategyKind.PreserveExisting && entry is not null)
+ {
+ return ConsumptionSaveResultKind.Skipped;
+ }
+ }
if (entry is null)
{
- entry = CultivateEntry.From(Projects.CurrentItem.InnerId, type, itemId);
+ entry = CultivateEntry.From(Projects.CurrentItem.InnerId, inputConsumption.Type, inputConsumption.ItemId);
cultivationDbService.AddCultivateEntry(entry);
}
Guid entryId = entry.InnerId;
cultivationDbService.RemoveLevelInformationByEntryId(entryId);
- CultivateEntryLevelInformation entryLevelInformation = CultivateEntryLevelInformation.From(entryId, type, levelInformation);
+ CultivateEntryLevelInformation entryLevelInformation = CultivateEntryLevelInformation.From(entryId, inputConsumption.Type, inputConsumption.LevelInformation);
cultivationDbService.AddLevelInformation(entryLevelInformation);
cultivationDbService.RemoveCultivateItemRangeByEntryId(entryId);
- IEnumerable toAdd = items.Select(item => CultivateItem.From(entryId, item));
+ IEnumerable toAdd = inputConsumption.Items.Select(item => CultivateItem.From(entryId, item));
cultivationDbService.AddCultivateItemRange(toAdd);
- return true;
+ return ConsumptionSaveResultKind.Added;
}
///
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs
index 06e2a724..64bc7eca 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationService.cs
@@ -3,22 +3,13 @@
using Snap.Hutao.Core.Database;
using Snap.Hutao.Model.Entity;
-using Snap.Hutao.Model.Entity.Primitive;
using Snap.Hutao.ViewModel.Cultivation;
-using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
using System.Collections.ObjectModel;
namespace Snap.Hutao.Service.Cultivation;
-///
-/// 养成计算服务
-///
-[HighQuality]
internal interface ICultivationService
{
- ///
- /// 获取用于绑定的项目集合
- ///
AdvancedDbCollectionView Projects { get; }
ValueTask> GetCultivateEntriesAsync(CultivateProject cultivateProject, ICultivationMetadataContext context);
@@ -26,32 +17,13 @@ internal interface ICultivationService
ValueTask> GetStatisticsCultivateItemCollectionAsync(
CultivateProject cultivateProject, ICultivationMetadataContext context, CancellationToken token);
- ///
- /// 删除养成清单
- ///
- /// 入口Id
- /// 任务
ValueTask RemoveCultivateEntryAsync(Guid entryId);
- ///
- /// 异步移除项目
- ///
- /// 项目
- /// 任务
ValueTask RemoveProjectAsync(CultivateProject project);
- ValueTask SaveConsumptionAsync(CultivateType type, uint itemId, List- items, LevelInformation levelInformation);
+ ValueTask SaveConsumptionAsync(InputConsumption inputConsumption);
- ///
- /// 保存养成物品状态
- ///
- /// 养成物品
void SaveCultivateItem(CultivateItemView item);
- ///
- /// 异步尝试添加新的项目
- ///
- /// 项目
- /// 添加操作的结果
ValueTask TryAddProjectAsync(CultivateProject project);
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/InputConsumption.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/InputConsumption.cs
new file mode 100644
index 00000000..605c5155
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/InputConsumption.cs
@@ -0,0 +1,20 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using Snap.Hutao.Model.Entity.Primitive;
+using CalculateItem = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Item;
+
+namespace Snap.Hutao.Service.Cultivation;
+
+internal sealed class InputConsumption
+{
+ public required CultivateType Type { get; init; }
+
+ public required uint ItemId { get; init; }
+
+ public required List Items { get; init; }
+
+ public required LevelInformation LevelInformation { get; init; }
+
+ public required ConsumptionSaveStrategyKind Strategy { get; init; }
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs
index a25c75bf..65b201f7 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs
@@ -203,7 +203,7 @@ internal sealed partial class GachaStatisticsFactory : IGachaStatisticsFactory
AsyncBarrier barrier = new(4);
List historyWishes = historyWishBuilders
- .Where(b => appOptions.IsEmptyHistoryWishVisible || (!b.IsEmpty))
+ .Where(b => appOptions.IsEmptyHistoryWishVisible || !b.IsEmpty)
.OrderByDescending(builder => builder.From)
.ThenBy(builder => builder.ConfigType, GachaTypeComparer.Shared)
.Select(builder => builder.ToHistoryWish())
@@ -212,7 +212,7 @@ internal sealed partial class GachaStatisticsFactory : IGachaStatisticsFactory
return new()
{
// history
- HistoryWishes = new(historyWishes),
+ HistoryWishes = historyWishes.ToAdvancedCollectionView(),
// avatars
OrangeAvatars = orangeAvatarCounter.ToStatisticsList(),
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs
index dbce927b..5b43cdb5 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs
@@ -21,9 +21,15 @@ internal sealed partial class GameAccountService : IGameAccountService
private ObservableReorderableDbCollection? gameAccounts;
- public ObservableReorderableDbCollection GameAccountCollection
+ public async ValueTask> GetGameAccountCollectionAsync()
{
- get => gameAccounts ??= gameDbService.GetGameAccountCollection();
+ if (gameAccounts is null)
+ {
+ await taskContext.SwitchToBackgroundAsync();
+ gameAccounts = gameDbService.GetGameAccountCollection();
+ }
+
+ return gameAccounts;
}
public async ValueTask DetectGameAccountAsync(SchemeType schemeType)
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs
index c3c7da9e..6a7c3d99 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs
@@ -9,14 +9,14 @@ namespace Snap.Hutao.Service.Game.Account;
internal interface IGameAccountService
{
- ObservableReorderableDbCollection GameAccountCollection { get; }
-
ValueTask AttachGameAccountToUidAsync(GameAccount gameAccount, string uid);
GameAccount? DetectCurrentGameAccount(SchemeType schemeType);
ValueTask DetectGameAccountAsync(SchemeType schemeType);
+ ValueTask> GetGameAccountCollectionAsync();
+
ValueTask ModifyGameAccountAsync(GameAccount gameAccount);
ValueTask RemoveGameAccountAsync(GameAccount gameAccount);
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs
index 9c011292..d604aeeb 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs
@@ -11,10 +11,6 @@ using Snap.Hutao.Service.Game.PathAbstraction;
namespace Snap.Hutao.Service.Game;
-///
-/// 游戏服务
-///
-[HighQuality]
[ConstructorGenerated]
[Injection(InjectAs.Singleton, typeof(IGameServiceFacade))]
internal sealed partial class GameServiceFacade : IGameServiceFacade
@@ -23,55 +19,46 @@ internal sealed partial class GameServiceFacade : IGameServiceFacade
private readonly IGameAccountService gameAccountService;
private readonly IGamePathService gamePathService;
- ///
- public ObservableReorderableDbCollection GameAccountCollection
+ public ValueTask> GetGameAccountCollectionAsync()
{
- get => gameAccountService.GameAccountCollection;
+ return gameAccountService.GetGameAccountCollectionAsync();
}
- ///
public ValueTask> GetGamePathAsync()
{
return gamePathService.SilentGetGamePathAsync();
}
- ///
public ChannelOptions GetChannelOptions()
{
return gameChannelOptionsService.GetChannelOptions();
}
- ///
public ValueTask DetectGameAccountAsync(SchemeType scheme)
{
return gameAccountService.DetectGameAccountAsync(scheme);
}
- ///
public GameAccount? DetectCurrentGameAccount(SchemeType scheme)
{
return gameAccountService.DetectCurrentGameAccount(scheme);
}
- ///
public ValueTask AttachGameAccountToUidAsync(GameAccount gameAccount, string uid)
{
return gameAccountService.AttachGameAccountToUidAsync(gameAccount, uid);
}
- ///
public ValueTask ModifyGameAccountAsync(GameAccount gameAccount)
{
return gameAccountService.ModifyGameAccountAsync(gameAccount);
}
- ///
public ValueTask RemoveGameAccountAsync(GameAccount gameAccount)
{
return gameAccountService.RemoveGameAccountAsync(gameAccount);
}
- ///
public bool IsGameRunning()
{
return LaunchExecutionEnsureGameNotRunningHandler.IsGameRunning(out _);
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs
index fcff98b9..707a6c98 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs
@@ -10,8 +10,6 @@ namespace Snap.Hutao.Service.Game;
internal interface IGameServiceFacade
{
- ObservableReorderableDbCollection GameAccountCollection { get; }
-
ValueTask AttachGameAccountToUidAsync(GameAccount gameAccount, string uid);
ValueTask DetectGameAccountAsync(SchemeType scheme);
@@ -27,4 +25,6 @@ internal interface IGameServiceFacade
ValueTask RemoveGameAccountAsync(GameAccount gameAccount);
GameAccount? DetectCurrentGameAccount(SchemeType scheme);
+
+ ValueTask> GetGameAccountCollectionAsync();
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/User/UserInitializationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/User/UserInitializationService.cs
index 612fec23..bcf53324 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/User/UserInitializationService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/User/UserInitializationService.cs
@@ -3,6 +3,7 @@
using Snap.Hutao.Core.DependencyInjection.Abstraction;
using Snap.Hutao.Model.Entity.Extension;
+using Snap.Hutao.UI.Xaml.Data;
using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.Bbs.User;
using Snap.Hutao.Web.Hoyolab.Passport;
@@ -213,7 +214,7 @@ internal sealed partial class UserInitializationService : IUserInitializationSer
if (userGameRolesResponse.IsOk())
{
- user.UserGameRoles = new(userGameRolesResponse.Data.List);
+ user.UserGameRoles = userGameRolesResponse.Data.List.ToAdvancedCollectionView();
return user.UserGameRoles.Count > 0;
}
else
diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/Layout/UniformStaggeredLayoutState.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/Layout/UniformStaggeredLayoutState.cs
index 6f31057d..5ec5f717 100644
--- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/Layout/UniformStaggeredLayoutState.cs
+++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/Layout/UniformStaggeredLayoutState.cs
@@ -100,7 +100,11 @@ internal sealed class UniformStaggeredLayoutState
internal void Clear()
{
- RecycleElements();
+ if (items.Count > 0)
+ {
+ RecycleElements();
+ }
+
ClearColumns();
ClearItems();
}
diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Data/AdvancedCollectionView.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Data/AdvancedCollectionView.cs
index ad9003c8..0253f741 100644
--- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Data/AdvancedCollectionView.cs
+++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Data/AdvancedCollectionView.cs
@@ -4,7 +4,6 @@
using CommunityToolkit.WinUI.Collections;
using CommunityToolkit.WinUI.Helpers;
using Microsoft.UI.Xaml.Data;
-using Snap.Hutao.Core.ExceptionService;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/AchievementImportDialog.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/AchievementImportDialog.xaml
index 99c594df..4628fa30 100644
--- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/AchievementImportDialog.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/AchievementImportDialog.xaml
@@ -60,7 +60,7 @@
-/// 成就对话框
-///
-[HighQuality]
[DependencyProperty("UIAF", typeof(UIAF))]
internal sealed partial class AchievementImportDialog : ContentDialog
{
private readonly ITaskContext taskContext;
- ///
- /// 构造一个新的成就对话框
- ///
- /// 服务提供器
- /// uiaf数据
public AchievementImportDialog(IServiceProvider serviceProvider, UIAF uiaf)
{
InitializeComponent();
@@ -30,10 +21,6 @@ internal sealed partial class AchievementImportDialog : ContentDialog
UIAF = uiaf;
}
- ///
- /// 异步获取导入选项
- ///
- /// 导入选项
public async ValueTask> GetImportStrategyAsync()
{
await taskContext.SwitchToMainThreadAsync();
diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaBatchDialog.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaBatchDialog.xaml
index d05cd114..17c63f7d 100644
--- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaBatchDialog.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaBatchDialog.xaml
@@ -73,5 +73,14 @@
SpinButtonPlacementMode="Inline"
Value="{x:Bind PromotionDelta.Weapon.LevelTarget, Mode=TwoWay}"/>
+
+
+
+
+
+
diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaBatchDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaBatchDialog.xaml.cs
index f854aa44..88f1ee4a 100644
--- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaBatchDialog.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaBatchDialog.xaml.cs
@@ -3,6 +3,7 @@
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Core.Setting;
+using Snap.Hutao.Service.Cultivation;
using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
namespace Snap.Hutao.UI.Xaml.View.Dialog;
@@ -21,7 +22,7 @@ internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
PromotionDelta = AvatarPromotionDelta.CreateForBaseline();
}
- public async ValueTask> GetPromotionDeltaBaselineAsync()
+ public async ValueTask> GetPromotionDeltaBaselineAsync()
{
await taskContext.SwitchToMainThreadAsync();
ContentDialogResult result = await ShowAsync();
@@ -50,6 +51,6 @@ internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
LocalSetting.Set(SettingKeys.CultivationWeapon90LevelTarget, weapon.LevelTarget);
}
- return new(true, PromotionDelta);
+ return new(true, new(PromotionDelta, (ConsumptionSaveStrategyKind)SaveModeSelector.SelectedIndex));
}
-}
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaDialog.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaDialog.xaml
index c1539985..241b706c 100644
--- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaDialog.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaDialog.xaml
@@ -64,16 +64,14 @@
-
+
+
-
+
-
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaDialog.xaml.cs
index 7a6c9433..c337a775 100644
--- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaDialog.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaDialog.xaml.cs
@@ -4,25 +4,17 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Model.Calculable;
+using Snap.Hutao.Service.Cultivation;
using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
namespace Snap.Hutao.UI.Xaml.View.Dialog;
-///
-/// 养成计算对话框
-///
-[HighQuality]
[DependencyProperty("Avatar", typeof(ICalculableAvatar))]
[DependencyProperty("Weapon", typeof(ICalculableWeapon))]
internal sealed partial class CultivatePromotionDeltaDialog : ContentDialog
{
private readonly ITaskContext taskContext;
- ///
- /// 构造一个新的养成计算对话框
- ///
- /// 服务提供器
- /// 选项
public CultivatePromotionDeltaDialog(IServiceProvider serviceProvider, CalculableOptions options)
{
InitializeComponent();
@@ -33,11 +25,7 @@ internal sealed partial class CultivatePromotionDeltaDialog : ContentDialog
Weapon = options.Weapon;
}
- ///
- /// 异步获取提升差异
- ///
- /// 提升差异
- public async ValueTask> GetPromotionDeltaAsync()
+ public async ValueTask> GetPromotionDeltaAsync()
{
await taskContext.SwitchToMainThreadAsync();
ContentDialogResult result = await ShowAsync();
@@ -66,6 +54,6 @@ internal sealed partial class CultivatePromotionDeltaDialog : ContentDialog
},
};
- return new(true, delta);
+ return new(true, new(delta, (ConsumptionSaveStrategyKind)SaveModeSelector.SelectedIndex));
}
-}
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaOptions.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaOptions.cs
new file mode 100644
index 00000000..859ec098
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaOptions.cs
@@ -0,0 +1,20 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using Snap.Hutao.Service.Cultivation;
+using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
+
+namespace Snap.Hutao.UI.Xaml.View.Dialog;
+
+internal sealed class CultivatePromotionDeltaOptions
+{
+ public CultivatePromotionDeltaOptions(AvatarPromotionDelta delta, ConsumptionSaveStrategyKind strategy)
+ {
+ Delta = delta;
+ Strategy = strategy;
+ }
+
+ public AvatarPromotionDelta Delta { get; set; }
+
+ public ConsumptionSaveStrategyKind Strategy { get; set; }
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/UIGFUidSelection.xaml.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/UIGFUidSelection.cs
similarity index 100%
rename from src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/UIGFUidSelection.xaml.cs
rename to src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/UIGFUidSelection.cs
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs
index 02117d00..e6e6fab5 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Achievement/AchievementViewModel.cs
@@ -107,13 +107,15 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav
///
public async ValueTask ReceiveAsync(INavigationData data)
{
- if (await Initialization.Task.ConfigureAwait(false))
+ if (!await Initialization.Task.ConfigureAwait(false))
{
- if (data.Data is AppActivation.ImportUIAFFromClipboard)
- {
- await ImportUIAFFromClipboardAsync().ConfigureAwait(false);
- return true;
- }
+ return false;
+ }
+
+ if (data.Data is AppActivation.ImportUIAFFromClipboard)
+ {
+ await ImportUIAFFromClipboardAsync().ConfigureAwait(false);
+ return true;
}
return false;
@@ -206,7 +208,7 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav
[Command("RemoveArchiveCommand")]
private async Task RemoveArchiveAsync()
{
- if (Archives is null || !(Archives.CurrentItem is { } current))
+ if (Archives?.CurrentItem is not { } current)
{
return;
}
@@ -283,7 +285,9 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav
private async ValueTask UpdateAchievementsAsync(EntityArchive? archive)
{
- // TODO: immediately clear values
+ await scopeContext.TaskContext.SwitchToMainThreadAsync();
+ Achievements = default;
+
if (archive is null)
{
return;
@@ -293,31 +297,29 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav
.GetContextAsync(CancellationToken)
.ConfigureAwait(false);
- if (!TryGetAchievements(archive, context, out List? combined))
+ if (!TryGetAchievements(archive, context, out AdvancedCollectionView? combined))
{
return;
}
- AdvancedCollectionView achievements = new(combined);
-
await scopeContext.TaskContext.SwitchToMainThreadAsync();
- Achievements = achievements;
+ Achievements = combined;
AchievementFinishPercent.Update(this);
UpdateAchievementsFilterByGoal(AchievementGoals?.CurrentItem);
UpdateAchievementsSort();
}
- private bool TryGetAchievements(EntityArchive archive, AchievementServiceMetadataContext context, [NotNullWhen(true)] out List? combined)
+ private bool TryGetAchievements(EntityArchive archive, AchievementServiceMetadataContext context, [NotNullWhen(true)] out AdvancedCollectionView? view)
{
try
{
- combined = scopeContext.AchievementService.GetAchievementViewList(archive, context);
+ view = scopeContext.AchievementService.GetAchievementViewList(archive, context).ToAdvancedCollectionView();
return true;
}
catch (HutaoException ex)
{
scopeContext.InfoBarService.Error(ex);
- combined = default;
+ view = default;
return false;
}
}
@@ -330,33 +332,41 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav
return;
}
- Achievements.SortDescriptions.Clear();
- AchievementGoals.SortDescriptions.Clear();
-
- if (IsUncompletedItemsFirst)
+ using (Achievements.DeferRefresh())
{
- Achievements.SortDescriptions.Add(achievementUncompletedItemsFirstSortDescription);
- Achievements.SortDescriptions.Add(achievementCompletionTimeSortDescription);
- AchievementGoals.SortDescriptions.Add(achievementGoalUncompletedItemsFirstSortDescription);
- }
+ using (AchievementGoals.DeferRefresh())
+ {
+ Achievements.SortDescriptions.Clear();
+ AchievementGoals.SortDescriptions.Clear();
- Achievements.SortDescriptions.Add(achievementDefaultSortDescription);
- AchievementGoals.SortDescriptions.Add(achievementGoalDefaultSortDescription);
+ if (IsUncompletedItemsFirst)
+ {
+ Achievements.SortDescriptions.Add(achievementUncompletedItemsFirstSortDescription);
+ Achievements.SortDescriptions.Add(achievementCompletionTimeSortDescription);
+ AchievementGoals.SortDescriptions.Add(achievementGoalUncompletedItemsFirstSortDescription);
+ }
+
+ Achievements.SortDescriptions.Add(achievementDefaultSortDescription);
+ AchievementGoals.SortDescriptions.Add(achievementGoalDefaultSortDescription);
+ }
+ }
}
private void UpdateAchievementsFilterByGoal(AchievementGoalView? goal)
{
- if (Achievements is not null)
+ if (Achievements is null)
{
- if (goal is null)
- {
- Achievements.Filter = default!;
- }
- else
- {
- Model.Primitive.AchievementGoalId goalId = goal.Id;
- Achievements.Filter = (AchievementView view) => view.Inner.Goal == goalId;
- }
+ return;
+ }
+
+ if (goal is null)
+ {
+ Achievements.Filter = default!;
+ }
+ else
+ {
+ Model.Primitive.AchievementGoalId goalId = goal.Id;
+ Achievements.Filter = (AchievementView view) => view.Inner.Goal == goalId;
}
}
@@ -398,10 +408,12 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav
[Command("SaveAchievementCommand")]
private void SaveAchievement(AchievementView? achievement)
{
- if (achievement is not null)
+ if (achievement is null)
{
- scopeContext.AchievementService.SaveAchievement(achievement);
- AchievementFinishPercent.Update(this);
+ return;
}
+
+ scopeContext.AchievementService.SaveAchievement(achievement);
+ AchievementFinishPercent.Update(this);
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModel.cs
index 4ffd0a3f..cb55f5d0 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModel.cs
@@ -3,9 +3,7 @@
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.UI.Xaml.Controls;
-using Snap.Hutao.Core.DataTransfer;
using Snap.Hutao.Core.ExceptionService;
-using Snap.Hutao.Factory.ContentDialog;
using Snap.Hutao.Model.Calculable;
using Snap.Hutao.Model.Entity.Primitive;
using Snap.Hutao.Service.AvatarInfo;
@@ -20,9 +18,7 @@ using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
using Snap.Hutao.Web.Response;
using CalculatorAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
using CalculatorBatchConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.BatchConsumption;
-using CalculatorClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient;
using CalculatorConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Consumption;
-using CalculatorItem = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Item;
using CalculatorItemHelper = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.ItemHelper;
namespace Snap.Hutao.ViewModel.AvatarProperty;
@@ -31,14 +27,7 @@ namespace Snap.Hutao.ViewModel.AvatarProperty;
[Injection(InjectAs.Scoped)]
internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, IRecipient
{
- private readonly IContentDialogFactory contentDialogFactory;
- private readonly ICultivationService cultivationService;
- private readonly IAvatarInfoService avatarInfoService;
- private readonly IClipboardProvider clipboardProvider;
- private readonly CalculatorClient calculatorClient;
- private readonly IInfoBarService infoBarService;
- private readonly ITaskContext taskContext;
- private readonly IUserService userService;
+ private readonly AvatarPropertyViewModelScopeContext scopeContext;
private Summary? summary;
@@ -61,7 +50,7 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
protected override async ValueTask InitializeOverrideAsync()
{
- if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid)
+ if (await scopeContext.UserService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid)
{
await RefreshCoreAsync(userAndUid, RefreshOption.None, CancellationToken).ConfigureAwait(false);
return true;
@@ -73,7 +62,7 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
[Command("RefreshFromEnkaApiCommand")]
private async Task RefreshByEnkaApiAsync()
{
- if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid)
+ if (await scopeContext.UserService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid)
{
await RefreshCoreAsync(userAndUid, RefreshOption.RequestFromEnkaAPI, CancellationToken).ConfigureAwait(false);
}
@@ -82,7 +71,7 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
[Command("RefreshFromHoyolabGameRecordCommand")]
private async Task RefreshByHoyolabGameRecordAsync()
{
- if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid)
+ if (await scopeContext.UserService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid)
{
await RefreshCoreAsync(userAndUid, RefreshOption.RequestFromHoyolabGameRecord, CancellationToken).ConfigureAwait(false);
}
@@ -91,7 +80,7 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
[Command("RefreshFromHoyolabCalculateCommand")]
private async Task RefreshByHoyolabCalculateAsync()
{
- if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid)
+ if (await scopeContext.UserService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid)
{
await RefreshCoreAsync(userAndUid, RefreshOption.RequestFromHoyolabCalculate, CancellationToken).ConfigureAwait(false);
}
@@ -101,18 +90,19 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
{
try
{
- await taskContext.SwitchToMainThreadAsync();
+ await scopeContext.TaskContext.SwitchToMainThreadAsync();
IsInitialized = false;
+
ValueResult summaryResult;
using (await EnterCriticalSectionAsync().ConfigureAwait(false))
{
- ContentDialog dialog = await contentDialogFactory
+ ContentDialog dialog = await scopeContext.ContentDialogFactory
.CreateForIndeterminateProgressAsync(SH.ViewModelAvatarPropertyFetch)
.ConfigureAwait(false);
- using (await dialog.BlockAsync(taskContext).ConfigureAwait(false))
+ using (await dialog.BlockAsync(scopeContext.TaskContext).ConfigureAwait(false))
{
- summaryResult = await avatarInfoService
+ summaryResult = await scopeContext.AvatarInfoService
.GetSummaryAsync(userAndUid, option, token)
.ConfigureAwait(false);
}
@@ -121,7 +111,7 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
(RefreshResultKind result, Summary? summary) = summaryResult;
if (result is RefreshResultKind.Ok)
{
- await taskContext.SwitchToMainThreadAsync();
+ await scopeContext.TaskContext.SwitchToMainThreadAsync();
Summary = summary;
Summary?.Avatars.MoveCurrentToFirstOrDefault();
}
@@ -130,16 +120,16 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
switch (result)
{
case RefreshResultKind.APIUnavailable:
- infoBarService.Warning(SH.ViewModelAvatarPropertyEnkaApiUnavailable);
+ scopeContext.InfoBarService.Warning(SH.ViewModelAvatarPropertyEnkaApiUnavailable);
break;
case RefreshResultKind.StatusCodeNotSucceed:
ArgumentNullException.ThrowIfNull(summary);
- infoBarService.Warning(summary.Message);
+ scopeContext.InfoBarService.Warning(summary.Message);
break;
case RefreshResultKind.ShowcaseNotOpen:
- infoBarService.Warning(SH.ViewModelAvatarPropertyShowcaseNotOpen);
+ scopeContext.InfoBarService.Warning(SH.ViewModelAvatarPropertyShowcaseNotOpen);
break;
}
}
@@ -149,7 +139,7 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
}
finally
{
- await taskContext.SwitchToMainThreadAsync();
+ await scopeContext.TaskContext.SwitchToMainThreadAsync();
IsInitialized = true;
}
}
@@ -162,41 +152,47 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
return;
}
- if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is not { } userAndUid)
+ if (await scopeContext.UserService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is not { } userAndUid)
{
- infoBarService.Warning(SH.MustSelectUserAndUid);
+ scopeContext.InfoBarService.Warning(SH.MustSelectUserAndUid);
return;
}
if (avatar.Weapon is null)
{
- infoBarService.Warning(SH.ViewModelAvatarPropertyCalculateWeaponNull);
+ scopeContext.InfoBarService.Warning(SH.ViewModelAvatarPropertyCalculateWeaponNull);
return;
}
CalculableOptions options = new(avatar.ToCalculable(), avatar.Weapon.ToCalculable());
- CultivatePromotionDeltaDialog dialog = await contentDialogFactory.CreateInstanceAsync(options).ConfigureAwait(false);
- (bool isOk, CalculatorAvatarPromotionDelta delta) = await dialog.GetPromotionDeltaAsync().ConfigureAwait(false);
+ CultivatePromotionDeltaDialog dialog = await scopeContext.ContentDialogFactory
+ .CreateInstanceAsync(options).ConfigureAwait(false);
+ (bool isOk, CultivatePromotionDeltaOptions deltaOptions) = await dialog.GetPromotionDeltaAsync().ConfigureAwait(false);
if (!isOk)
{
return;
}
- Response response = await calculatorClient.BatchComputeAsync(userAndUid, delta).ConfigureAwait(false);
+ Response response;
+ using (IServiceScope scope = scopeContext.ServiceScopeFactory.CreateScope())
+ {
+ CalculateClient calculatorClient = scope.ServiceProvider.GetRequiredService();
+ response = await calculatorClient.BatchComputeAsync(userAndUid, deltaOptions.Delta).ConfigureAwait(false);
+ }
if (!response.IsOk())
{
return;
}
- if (!await SaveCultivationAsync(response.Data.Items.Single(), delta).ConfigureAwait(false))
+ if (!await SaveCultivationAsync(response.Data.Items.Single(), deltaOptions).ConfigureAwait(false))
{
- infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
+ scopeContext.InfoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
return;
}
- infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
+ scopeContext.InfoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
}
[Command("BatchCultivateCommand")]
@@ -207,34 +203,35 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
return;
}
- if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is not { } userAndUid)
+ if (await scopeContext.UserService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is not { } userAndUid)
{
- infoBarService.Warning(SH.MustSelectUserAndUid);
+ scopeContext.InfoBarService.Warning(SH.MustSelectUserAndUid);
return;
}
- CultivatePromotionDeltaBatchDialog dialog = await contentDialogFactory.CreateInstanceAsync().ConfigureAwait(false);
- (bool isOk, CalculatorAvatarPromotionDelta baseline) = await dialog.GetPromotionDeltaBaselineAsync().ConfigureAwait(false);
+ CultivatePromotionDeltaBatchDialog dialog = await scopeContext.ContentDialogFactory
+ .CreateInstanceAsync().ConfigureAwait(false);
+ (bool isOk, CultivatePromotionDeltaOptions deltaOptions) = await dialog.GetPromotionDeltaBaselineAsync().ConfigureAwait(false);
if (!isOk)
{
return;
}
- ArgumentNullException.ThrowIfNull(baseline.SkillList);
- ArgumentNullException.ThrowIfNull(baseline.Weapon);
+ ArgumentNullException.ThrowIfNull(deltaOptions.Delta.SkillList);
+ ArgumentNullException.ThrowIfNull(deltaOptions.Delta.Weapon);
- ContentDialog progressDialog = await contentDialogFactory
+ ContentDialog progressDialog = await scopeContext.ContentDialogFactory
.CreateForIndeterminateProgressAsync(SH.ViewModelAvatarPropertyBatchCultivateProgressTitle)
.ConfigureAwait(false);
BatchCultivateResult result = default;
- using (await progressDialog.BlockAsync(taskContext).ConfigureAwait(false))
+ using (await progressDialog.BlockAsync(scopeContext.TaskContext).ConfigureAwait(false))
{
List deltas = [];
foreach (AvatarView avatar in avatars)
{
- if (!baseline.TryGetNonErrorCopy(avatar, out CalculatorAvatarPromotionDelta? copy))
+ if (!deltaOptions.Delta.TryGetNonErrorCopy(avatar, out CalculatorAvatarPromotionDelta? copy))
{
++result.SkippedCount;
continue;
@@ -243,7 +240,12 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
deltas.Add(copy);
}
- Response response = await calculatorClient.BatchComputeAsync(userAndUid, deltas).ConfigureAwait(false);
+ Response response;
+ using (IServiceScope scope = scopeContext.ServiceScopeFactory.CreateScope())
+ {
+ CalculateClient calculatorClient = scope.ServiceProvider.GetRequiredService();
+ response = await calculatorClient.BatchComputeAsync(userAndUid, deltas).ConfigureAwait(false);
+ }
if (!response.IsOk())
{
@@ -252,9 +254,8 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
foreach ((CalculatorConsumption consumption, CalculatorAvatarPromotionDelta delta) in response.Data.Items.Zip(deltas))
{
- if (!await SaveCultivationAsync(consumption, delta).ConfigureAwait(false))
+ if (!await SaveCultivationAsync(consumption, new(delta, deltaOptions.Strategy)).ConfigureAwait(false))
{
- result.Interrupted = true;
break;
}
@@ -262,42 +263,70 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
}
}
- if (result.Interrupted)
+ if (result.SkippedCount > 0)
{
- infoBarService.Warning(SH.FormatViewModelCultivationBatchAddIncompletedFormat(result.SucceedCount, result.SkippedCount));
+ scopeContext.InfoBarService.Warning(SH.FormatViewModelCultivationBatchAddIncompletedFormat(result.SucceedCount, result.SkippedCount));
}
else
{
- infoBarService.Success(SH.FormatViewModelCultivationBatchAddCompletedFormat(result.SucceedCount, result.SkippedCount));
+ scopeContext.InfoBarService.Success(SH.FormatViewModelCultivationBatchAddCompletedFormat(result.SucceedCount, result.SkippedCount));
}
}
- private async ValueTask SaveCultivationAsync(CalculatorConsumption consumption, CalculatorAvatarPromotionDelta delta)
+ /// if we can continue saving consumptions, otherwise .
+ private async ValueTask SaveCultivationAsync(CalculatorConsumption consumption, CultivatePromotionDeltaOptions options)
{
- LevelInformation levelInformation = LevelInformation.From(delta);
+ LevelInformation levelInformation = LevelInformation.From(options.Delta);
- List items = CalculatorItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume);
- bool avatarSaved = await cultivationService
- .SaveConsumptionAsync(CultivateType.AvatarAndSkill, delta.AvatarId, items, levelInformation)
- .ConfigureAwait(false);
+ InputConsumption avatarInput = new()
+ {
+ Type = CultivateType.AvatarAndSkill,
+ ItemId = options.Delta.AvatarId,
+ Items = CalculatorItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume),
+ LevelInformation = levelInformation,
+ Strategy = options.Strategy,
+ };
+
+ ConsumptionSaveResultKind avatarSaveKind = await scopeContext.CultivationService.SaveConsumptionAsync(avatarInput).ConfigureAwait(false);
+
+ switch (avatarSaveKind)
+ {
+ case ConsumptionSaveResultKind.NoProject:
+ scopeContext.InfoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
+ return false;
+ case ConsumptionSaveResultKind.Skipped:
+ scopeContext.InfoBarService.Information(SH.ViewModelCultivationConsumptionSaveSkippedHint);
+ break;
+ case ConsumptionSaveResultKind.NoItem:
+ scopeContext.InfoBarService.Information(SH.ViewModelCultivationConsumptionSaveNoItemHint);
+ break;
+ case ConsumptionSaveResultKind.Added:
+ break;
+ }
try
{
- ArgumentNullException.ThrowIfNull(delta.Weapon);
+ ArgumentNullException.ThrowIfNull(options.Delta.Weapon);
- // Take a hot path if avatar is not saved.
- bool avatarAndWeaponSaved = avatarSaved && await cultivationService
- .SaveConsumptionAsync(CultivateType.Weapon, delta.Weapon.Id, consumption.WeaponConsume.EmptyIfNull(), levelInformation)
- .ConfigureAwait(false);
+ InputConsumption weaponInput = new()
+ {
+ Type = CultivateType.Weapon,
+ ItemId = options.Delta.Weapon.Id,
+ Items = consumption.WeaponConsume.EmptyIfNull(),
+ LevelInformation = levelInformation,
+ Strategy = options.Strategy,
+ };
- return avatarAndWeaponSaved;
+ ConsumptionSaveResultKind weaponSaveKind = await scopeContext.CultivationService.SaveConsumptionAsync(weaponInput).ConfigureAwait(false);
+
+ return weaponSaveKind is not ConsumptionSaveResultKind.NoProject;
}
catch (HutaoException ex)
{
- infoBarService.Error(ex, SH.ViewModelCultivationAddWarning);
+ scopeContext.InfoBarService.Error(ex, SH.ViewModelCultivationAddWarning);
}
- return true;
+ return false;
}
[Command("ExportToTextCommand")]
@@ -308,13 +337,13 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
return;
}
- if (clipboardProvider.SetText(AvatarViewTextTemplating.GetTemplatedText(avatar)))
+ if (scopeContext.ClipboardProvider.SetText(AvatarViewTextTemplating.GetTemplatedText(avatar)))
{
- infoBarService.Success(SH.ViewModelAvatatPropertyExportTextSuccess);
+ scopeContext.InfoBarService.Success(SH.ViewModelAvatatPropertyExportTextSuccess);
}
else
{
- infoBarService.Warning(SH.ViewModelAvatatPropertyExportTextError);
+ scopeContext.InfoBarService.Warning(SH.ViewModelAvatatPropertyExportTextError);
}
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModelScopeContext.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModelScopeContext.cs
new file mode 100644
index 00000000..e2baf5e7
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarPropertyViewModelScopeContext.cs
@@ -0,0 +1,41 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using Snap.Hutao.Core.DataTransfer;
+using Snap.Hutao.Factory.ContentDialog;
+using Snap.Hutao.Service.AvatarInfo;
+using Snap.Hutao.Service.Cultivation;
+using Snap.Hutao.Service.Notification;
+using Snap.Hutao.Service.User;
+
+namespace Snap.Hutao.ViewModel.AvatarProperty;
+
+[ConstructorGenerated]
+[Injection(InjectAs.Scoped)]
+internal sealed partial class AvatarPropertyViewModelScopeContext
+{
+ private readonly IContentDialogFactory contentDialogFactory;
+ private readonly IServiceScopeFactory serviceScopeFactory;
+ private readonly ICultivationService cultivationService;
+ private readonly IAvatarInfoService avatarInfoService;
+ private readonly IClipboardProvider clipboardProvider;
+ private readonly IInfoBarService infoBarService;
+ private readonly ITaskContext taskContext;
+ private readonly IUserService userService;
+
+ public IContentDialogFactory ContentDialogFactory { get => contentDialogFactory; }
+
+ public IServiceScopeFactory ServiceScopeFactory { get => serviceScopeFactory; }
+
+ public ICultivationService CultivationService { get => cultivationService; }
+
+ public IAvatarInfoService AvatarInfoService { get => avatarInfoService; }
+
+ public IClipboardProvider ClipboardProvider { get => clipboardProvider; }
+
+ public IInfoBarService InfoBarService { get => infoBarService; }
+
+ public ITaskContext TaskContext { get => taskContext; }
+
+ public IUserService UserService { get => userService; }
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/BatchCultivateResult.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/BatchCultivateResult.cs
index 1d24a185..895068c6 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/BatchCultivateResult.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/BatchCultivateResult.cs
@@ -7,5 +7,4 @@ internal struct BatchCultivateResult
{
public int SucceedCount;
public int SkippedCount;
- public bool Interrupted;
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs
index 24f76e87..816eb8d5 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs
@@ -325,7 +325,7 @@ internal sealed partial class LaunchGameViewModel : Abstraction.ViewModel, IView
async ValueTask UpdateGameAccountsViewAsync()
{
gameAccountFilter = new(SelectedScheme?.GetSchemeType());
- ObservableReorderableDbCollection accounts = gameService.GameAccountCollection;
+ ObservableReorderableDbCollection accounts = await gameService.GetGameAccountCollectionAsync().ConfigureAwait(false);
AdvancedCollectionView accountsView = new(accounts) { Filter = gameAccountFilter.Filter };
await taskContext.SwitchToMainThreadAsync();
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModelSlim.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModelSlim.cs
index 3bc49e15..1825ee16 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModelSlim.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModelSlim.cs
@@ -43,13 +43,14 @@ internal sealed partial class LaunchGameViewModelSlim : Abstraction.ViewModelSli
protected override async Task LoadAsync()
{
LaunchScheme? scheme = launchGameShared.GetCurrentLaunchSchemeFromConfigFile();
- ObservableCollection accounts = gameService.GameAccountCollection;
+ ObservableCollection accounts = await gameService.GetGameAccountCollectionAsync().ConfigureAwait(false);
try
{
if (scheme is not null)
{
// Try set to the current account.
+ await taskContext.SwitchToMainThreadAsync();
SelectedGameAccount ??= gameService.DetectCurrentGameAccount(scheme);
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingGachaLogViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingGachaLogViewModel.cs
index 2b93fe7f..b6fb3869 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingGachaLogViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingGachaLogViewModel.cs
@@ -4,7 +4,6 @@
using Snap.Hutao.Core.IO;
using Snap.Hutao.Factory.ContentDialog;
using Snap.Hutao.Factory.Picker;
-using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.InterChange.GachaLog;
using Snap.Hutao.Service;
using Snap.Hutao.Service.GachaLog;
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssRecordViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssRecordViewModel.cs
index 042466d0..4ec178ab 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssRecordViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssRecordViewModel.cs
@@ -85,7 +85,7 @@ internal sealed partial class SpiralAbyssRecordViewModel : Abstraction.ViewModel
.ConfigureAwait(false);
}
- AdvancedCollectionView spiralAbyssEntries = new(collection);
+ AdvancedCollectionView spiralAbyssEntries = collection.ToAdvancedCollectionView();
await taskContext.SwitchToMainThreadAsync();
SpiralAbyssEntries = spiralAbyssEntries;
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs
index 626523ef..f09c0910 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs
@@ -24,7 +24,6 @@ using Snap.Hutao.Web.Response;
using System.Collections.Frozen;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
-using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
using CalculateBatchConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.BatchConsumption;
using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient;
@@ -43,8 +42,8 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
private readonly IMetadataService metadataService;
private readonly ITaskContext taskContext;
private readonly IHutaoSpiralAbyssStatisticsCache hutaoCache;
+ private readonly IServiceScopeFactory serviceScopeFactory;
private readonly IInfoBarService infoBarService;
- private readonly CalculateClient calculateClient;
private readonly IUserService userService;
private AdvancedCollectionView? avatars;
@@ -109,7 +108,7 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
using (await EnterCriticalSectionAsync().ConfigureAwait(false))
{
- AdvancedCollectionView avatarsView = new(list);
+ AdvancedCollectionView avatarsView = list.ToAdvancedCollectionView();
await taskContext.SwitchToMainThreadAsync();
Avatars = avatarsView;
@@ -173,16 +172,19 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
CalculableOptions options = new(avatar.ToCalculable(), null);
CultivatePromotionDeltaDialog dialog = await contentDialogFactory.CreateInstanceAsync(options).ConfigureAwait(false);
- (bool isOk, CalculateAvatarPromotionDelta delta) = await dialog.GetPromotionDeltaAsync().ConfigureAwait(false);
+ (bool isOk, CultivatePromotionDeltaOptions deltaOptions) = await dialog.GetPromotionDeltaAsync().ConfigureAwait(false);
if (!isOk)
{
return;
}
- Response response = await calculateClient
- .BatchComputeAsync(userAndUid, delta)
- .ConfigureAwait(false);
+ Response response;
+ using (IServiceScope scope = serviceScopeFactory.CreateScope())
+ {
+ CalculateClient calculateClient = scope.ServiceProvider.GetRequiredService();
+ response = await calculateClient.BatchComputeAsync(userAndUid, deltaOptions.Delta).ConfigureAwait(false);
+ }
if (!response.IsOk())
{
@@ -190,20 +192,32 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
}
CalculateBatchConsumption batchConsumption = response.Data;
- LevelInformation levelInformation = LevelInformation.From(delta);
+ LevelInformation levelInformation = LevelInformation.From(deltaOptions.Delta);
try
{
- bool saved = await cultivationService
- .SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, batchConsumption.OverallConsume, levelInformation)
- .ConfigureAwait(false);
+ InputConsumption input = new()
+ {
+ Type = CultivateType.AvatarAndSkill,
+ ItemId = avatar.Id,
+ Items = batchConsumption.OverallConsume,
+ LevelInformation = levelInformation,
+ Strategy = deltaOptions.Strategy,
+ };
- if (saved)
+ switch (await cultivationService.SaveConsumptionAsync(input).ConfigureAwait(false))
{
- infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
- }
- else
- {
- infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
+ case ConsumptionSaveResultKind.NoProject:
+ infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
+ break;
+ case ConsumptionSaveResultKind.Skipped:
+ infoBarService.Information(SH.ViewModelCultivationConsumptionSaveSkippedHint);
+ break;
+ case ConsumptionSaveResultKind.NoItem:
+ infoBarService.Information(SH.ViewModelCultivationConsumptionSaveNoItemHint);
+ break;
+ case ConsumptionSaveResultKind.Added:
+ infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
+ break;
}
}
catch (HutaoException ex)
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiMonsterViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiMonsterViewModel.cs
index 74e1d10c..14dd4f2c 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiMonsterViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiMonsterViewModel.cs
@@ -68,7 +68,7 @@ internal sealed partial class WikiMonsterViewModel : Abstraction.ViewModel
using (await EnterCriticalSectionAsync().ConfigureAwait(false))
{
- AdvancedCollectionView monstersView = new(ordered);
+ AdvancedCollectionView monstersView = ordered.ToAdvancedCollectionView();
await taskContext.SwitchToMainThreadAsync();
Monsters = monstersView;
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs
index 1a0cec91..cbe33de6 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs
@@ -24,7 +24,6 @@ using Snap.Hutao.Web.Response;
using System.Collections.Frozen;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
-using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
using CalculateBatchConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.BatchConsumption;
using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient;
@@ -38,11 +37,11 @@ namespace Snap.Hutao.ViewModel.Wiki;
internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel
{
private readonly IContentDialogFactory contentDialogFactory;
- private readonly CalculateClient calculateClient;
private readonly ICultivationService cultivationService;
private readonly ITaskContext taskContext;
private readonly IMetadataService metadataService;
private readonly IHutaoSpiralAbyssStatisticsCache hutaoCache;
+ private readonly IServiceScopeFactory serviceScopeFactory;
private readonly IInfoBarService infoBarService;
private readonly IUserService userService;
@@ -108,7 +107,7 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel
using (await EnterCriticalSectionAsync().ConfigureAwait(false))
{
- AdvancedCollectionView weaponsView = new(list);
+ AdvancedCollectionView weaponsView = list.ToAdvancedCollectionView();
await taskContext.SwitchToMainThreadAsync();
@@ -168,16 +167,19 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel
CalculableOptions options = new(null, weapon.ToCalculable());
CultivatePromotionDeltaDialog dialog = await contentDialogFactory.CreateInstanceAsync(options).ConfigureAwait(false);
- (bool isOk, CalculateAvatarPromotionDelta delta) = await dialog.GetPromotionDeltaAsync().ConfigureAwait(false);
+ (bool isOk, CultivatePromotionDeltaOptions deltaOptions) = await dialog.GetPromotionDeltaAsync().ConfigureAwait(false);
if (!isOk)
{
return;
}
- Response response = await calculateClient
- .BatchComputeAsync(userAndUid, delta)
- .ConfigureAwait(false);
+ Response response;
+ using (IServiceScope scope = serviceScopeFactory.CreateScope())
+ {
+ CalculateClient calculateClient = scope.ServiceProvider.GetRequiredService();
+ response = await calculateClient.BatchComputeAsync(userAndUid, deltaOptions.Delta).ConfigureAwait(false);
+ }
if (!response.IsOk())
{
@@ -185,20 +187,32 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel
}
CalculateBatchConsumption batchConsumption = response.Data;
- LevelInformation levelInformation = LevelInformation.From(delta);
+ LevelInformation levelInformation = LevelInformation.From(deltaOptions.Delta);
try
{
- bool saved = await cultivationService
- .SaveConsumptionAsync(CultivateType.Weapon, weapon.Id, batchConsumption.OverallConsume, levelInformation)
- .ConfigureAwait(false);
+ InputConsumption input = new()
+ {
+ Type = CultivateType.Weapon,
+ ItemId = weapon.Id,
+ Items = batchConsumption.OverallConsume,
+ LevelInformation = levelInformation,
+ Strategy = deltaOptions.Strategy,
+ };
- if (saved)
+ switch (await cultivationService.SaveConsumptionAsync(input).ConfigureAwait(false))
{
- infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
- }
- else
- {
- infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
+ case ConsumptionSaveResultKind.NoProject:
+ infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
+ break;
+ case ConsumptionSaveResultKind.Skipped:
+ infoBarService.Information(SH.ViewModelCultivationConsumptionSaveSkippedHint);
+ break;
+ case ConsumptionSaveResultKind.NoItem:
+ infoBarService.Information(SH.ViewModelCultivationConsumptionSaveNoItemHint);
+ break;
+ case ConsumptionSaveResultKind.Added:
+ infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
+ break;
}
}
catch (HutaoException ex)