diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Cultivation/CultivateProjectAvatarPropertyBatchPreferences.cs b/src/Snap.Hutao/Snap.Hutao/Model/Cultivation/CultivateProjectAvatarPropertyBatchPreferences.cs index 1f79c48..d295a56 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Cultivation/CultivateProjectAvatarPropertyBatchPreferences.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Cultivation/CultivateProjectAvatarPropertyBatchPreferences.cs @@ -21,4 +21,14 @@ internal sealed class CultivateProjectAvatarPropertyBatchPreferences public int ConsumptionSaveStrategyIndex { get; set; } public bool ClearAvatarAndWeaponEntriesBeforeSync { get; set; } + + /// + /// 执行批量前是否先通过养成计算器将游戏背包同步到当前计划(与养成计划「同步背包物品」一致)。 + /// + public bool SyncInventoryItems { get; set; } + + /// + /// 执行批量前是否先从米游社原神战绩同步「我的角色」数据(与我的角色「同步角色信息」一致)。 + /// + public bool SyncCharacterInfo { get; set; } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/AvatarPropertyBatchCultivateService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/AvatarPropertyBatchCultivateService.cs index a86e938..b017724 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/AvatarPropertyBatchCultivateService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/AvatarPropertyBatchCultivateService.cs @@ -5,10 +5,17 @@ using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Cultivation; +using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity.Primitive; +using Snap.Hutao.Model.Primitive; +using Snap.Hutao.Service.AvatarInfo; using Snap.Hutao.Service.AvatarInfo.Factory; using Snap.Hutao.Service.Cultivation.Consumption; using Snap.Hutao.Service.Cultivation.Offline; +using Snap.Hutao.Service.Inventory; +using Snap.Hutao.Service.Metadata; +using Snap.Hutao.Service.Metadata.ContextAbstraction; +using Snap.Hutao.Service.User; using Snap.Hutao.UI.Xaml.View.Dialog; using Snap.Hutao.ViewModel.AvatarProperty; using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate; @@ -62,13 +69,66 @@ internal sealed partial class AvatarPropertyBatchCultivateService : IAvatarPrope BatchCultivateResult result = default; using (await contentDialogFactory.BlockAsync(progressDialog).ConfigureAwait(false)) { + ImmutableArray avatarsToProcess = targetAvatars; + + if (baseline.SyncCharacterInfo) + { + IUserService userService = serviceProvider.GetRequiredService(); + if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid) + { + IServiceScopeFactory scopeFactory = serviceProvider.GetRequiredService(); + using (IServiceScope scope = scopeFactory.CreateScope()) + { + IAvatarInfoService avatarInfoService = scope.ServiceProvider.GetRequiredService(); + Summary? refreshed = await avatarInfoService + .GetSummaryAsync(metadataContext, userAndUid, global::Snap.Hutao.Service.AvatarInfo.RefreshOptionKind.RequestFromHoyolabGameRecord, cancellationToken) + .ConfigureAwait(false); + + if (refreshed?.Avatars.Source is { Count: > 0 } sourceAvatars) + { + HashSet wanted = [.. targetAvatars.Select(static a => a.Id)]; + ImmutableArray.Builder filtered = ImmutableArray.CreateBuilder(); + foreach (AvatarView avatar in sourceAvatars) + { + if (wanted.Contains(avatar.Id)) + { + filtered.Add(avatar); + } + } + + if (filtered.Count > 0) + { + avatarsToProcess = filtered.ToImmutable(); + } + } + } + } + } + + if (baseline.SyncInventoryItems) + { + CultivateProject? project = await cultivationService.GetCurrentProjectAsync().ConfigureAwait(false); + if (project is not null) + { + IMetadataService metadataService = serviceProvider.GetRequiredService(); + ICultivationMetadataContext cultivationContext = await metadataService + .GetContextAsync(cancellationToken) + .ConfigureAwait(false); + + IInventoryService inventoryService = serviceProvider.GetRequiredService(); + await inventoryService + .RefreshInventoryAsync(RefreshOptions.CreateForWebCalculator(project, cultivationContext)) + .ConfigureAwait(false); + } + } + if (baseline.ClearAvatarAndWeaponEntriesBeforeSync) { await cultivationService.RemoveAvatarAndWeaponEntriesForCurrentProjectAsync().ConfigureAwait(false); } ImmutableArray.Builder deltasBuilder = ImmutableArray.CreateBuilder(); - foreach (AvatarView avatar in targetAvatars) + foreach (AvatarView avatar in avatarsToProcess) { if (!baseline.Delta.TryGetNonErrorCopy(avatar, out CalculatorAvatarPromotionDelta? copy)) { @@ -121,6 +181,8 @@ internal sealed partial class AvatarPropertyBatchCultivateService : IAvatarPrope WeaponLevelTarget = d.Weapon?.LevelTarget ?? 90U, ConsumptionSaveStrategyIndex = (int)baseline.Strategy, ClearAvatarAndWeaponEntriesBeforeSync = baseline.ClearAvatarAndWeaponEntriesBeforeSync, + SyncInventoryItems = baseline.SyncInventoryItems, + SyncCharacterInfo = baseline.SyncCharacterInfo, }; } 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 639212a..9a8abf0 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 @@ -20,7 +20,9 @@ 0 0 - + + + - + + + + \ No newline at end of file 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 e08a810..18f7b95 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 @@ -12,6 +12,8 @@ namespace Snap.Hutao.UI.Xaml.View.Dialog; [DependencyProperty("PromotionDelta", NotNull = true, CreateDefaultValueCallbackName = nameof(CreatePromotionDeltaDefaultValue))] [DependencyProperty("ClearAvatarAndWeaponEntriesBeforeSync", DefaultValue = false, NotNull = true)] +[DependencyProperty("SyncInventoryItems", DefaultValue = false, NotNull = true)] +[DependencyProperty("SyncCharacterInfo", DefaultValue = false, NotNull = true)] internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog { private readonly IContentDialogFactory contentDialogFactory; @@ -56,7 +58,7 @@ internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog LocalSetting.Set(SettingKeys.CultivationWeapon90LevelTarget, weapon.LevelTarget); } - return new(true, new CultivatePromotionDeltaOptions(PromotionDelta, (ConsumptionSaveStrategyKind)SaveModeSelector.SelectedIndex, ClearAvatarAndWeaponEntriesBeforeSync)); + return new(true, new CultivatePromotionDeltaOptions(PromotionDelta, (ConsumptionSaveStrategyKind)SaveModeSelector.SelectedIndex, ClearAvatarAndWeaponEntriesBeforeSync, SyncInventoryItems, SyncCharacterInfo)); } private void ApplyInitialPreferences(CultivateProjectAvatarPropertyBatchPreferences p) @@ -77,6 +79,8 @@ internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog SaveModeSelector.SelectedIndex = int.Clamp(p.ConsumptionSaveStrategyIndex, 0, 2); ClearAvatarAndWeaponEntriesBeforeSync = p.ClearAvatarAndWeaponEntriesBeforeSync; + SyncInventoryItems = p.SyncInventoryItems; + SyncCharacterInfo = p.SyncCharacterInfo; } private static object CreatePromotionDeltaDefaultValue() 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 index f374f64..3326ccc 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Dialog/CultivatePromotionDeltaOptions.cs @@ -8,7 +8,7 @@ namespace Snap.Hutao.UI.Xaml.View.Dialog; internal sealed class CultivatePromotionDeltaOptions { - public CultivatePromotionDeltaOptions(AvatarPromotionDelta delta, ConsumptionSaveStrategyKind strategy, bool clearAvatarAndWeaponEntriesBeforeSync = false) + public CultivatePromotionDeltaOptions(AvatarPromotionDelta delta, ConsumptionSaveStrategyKind strategy, bool clearAvatarAndWeaponEntriesBeforeSync = false, bool syncInventoryItems = false, bool syncCharacterInfo = false) { delta.AvatarLevelTarget = delta.AvatarLevelTarget switch { @@ -20,6 +20,8 @@ internal sealed class CultivatePromotionDeltaOptions Delta = delta; Strategy = strategy; ClearAvatarAndWeaponEntriesBeforeSync = clearAvatarAndWeaponEntriesBeforeSync; + SyncInventoryItems = syncInventoryItems; + SyncCharacterInfo = syncCharacterInfo; } public AvatarPromotionDelta Delta { get; } @@ -30,4 +32,8 @@ internal sealed class CultivatePromotionDeltaOptions /// 批量同步前是否清空当前计划中已有的角色与武器养成条目(不含家具等其它类型)。 /// public bool ClearAvatarAndWeaponEntriesBeforeSync { get; } + + public bool SyncInventoryItems { get; } + + public bool SyncCharacterInfo { get; } } \ No newline at end of file