mirror of
https://github.com/wangdage12/Snap.Hutao.git
synced 2026-07-31 04:10:25 +08:00
在 我的角色 同步角色 批量添加或更新到当前养成计划时,增加 清空已经角色和武器信息 勾选框。如勾选该项目,在更新计划前会清空 培养计划中,角色和武器的信息。另外,当点 确认,更新完数据后,刷新现 养成计划。
This commit is contained in:
@@ -1349,6 +1349,9 @@ Space Available: {2}</value>
|
|||||||
<data name="ViewDialogCultivateBatchWeaponLevelTarget" xml:space="preserve">
|
<data name="ViewDialogCultivateBatchWeaponLevelTarget" xml:space="preserve">
|
||||||
<value>Weapon Target Level</value>
|
<value>Weapon Target Level</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewDialogCultivateBatchClearAvatarAndWeaponEntries" xml:space="preserve">
|
||||||
|
<value>Clear existing character and weapon entries before updating</value>
|
||||||
|
</data>
|
||||||
<data name="ViewDialogCultivateProjectInputPlaceholder" xml:space="preserve">
|
<data name="ViewDialogCultivateProjectInputPlaceholder" xml:space="preserve">
|
||||||
<value>Enter the plan name here</value>
|
<value>Enter the plan name here</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -1391,6 +1391,9 @@
|
|||||||
<data name="ViewDialogCultivateBatchWeaponLevelTarget" xml:space="preserve">
|
<data name="ViewDialogCultivateBatchWeaponLevelTarget" xml:space="preserve">
|
||||||
<value>武器目标等级</value>
|
<value>武器目标等级</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewDialogCultivateBatchClearAvatarAndWeaponEntries" xml:space="preserve">
|
||||||
|
<value>更新计划前先清空已有角色与武器条目</value>
|
||||||
|
</data>
|
||||||
<data name="ViewDialogCultivateProjectInputPlaceholder" xml:space="preserve">
|
<data name="ViewDialogCultivateProjectInputPlaceholder" xml:space="preserve">
|
||||||
<value>在此处输入计划名称</value>
|
<value>在此处输入计划名称</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -178,6 +178,48 @@ internal sealed partial class CultivationService : ICultivationService
|
|||||||
cultivationRepository.RemoveCultivateEntryById(entryId);
|
cultivationRepository.RemoveCultivateEntryById(entryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask RemoveAvatarAndWeaponEntriesForCurrentProjectAsync()
|
||||||
|
{
|
||||||
|
IAdvancedDbCollectionView<CultivateProject> projects = await GetProjectCollectionAsync().ConfigureAwait(false);
|
||||||
|
if (!await EnsureCurrentProjectAsync(projects).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgumentNullException.ThrowIfNull(projects.CurrentItem);
|
||||||
|
Guid projectId = projects.CurrentItem.InnerId;
|
||||||
|
|
||||||
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
|
|
||||||
|
ImmutableArray<CultivateEntry> entries = cultivationRepository.GetCultivateEntryImmutableArrayByProjectId(projectId);
|
||||||
|
List<Guid> weaponEntryIds = new(entries.Length);
|
||||||
|
List<Guid> avatarEntryIds = new(entries.Length);
|
||||||
|
foreach (ref readonly CultivateEntry entry in entries.AsSpan())
|
||||||
|
{
|
||||||
|
switch (entry.Type)
|
||||||
|
{
|
||||||
|
case CultivateType.Weapon:
|
||||||
|
weaponEntryIds.Add(entry.InnerId);
|
||||||
|
break;
|
||||||
|
case CultivateType.AvatarAndSkill:
|
||||||
|
avatarEntryIds.Add(entry.InnerId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Guid id in weaponEntryIds)
|
||||||
|
{
|
||||||
|
cultivationRepository.RemoveCultivateEntryById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Guid id in avatarEntryIds)
|
||||||
|
{
|
||||||
|
cultivationRepository.RemoveCultivateEntryById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
entryCollectionCache.TryRemove(projectId, out _);
|
||||||
|
}
|
||||||
|
|
||||||
public void SaveCultivateItem(CultivateItemView item)
|
public void SaveCultivateItem(CultivateItemView item)
|
||||||
{
|
{
|
||||||
cultivationRepository.UpdateCultivateItem(item.Entity);
|
cultivationRepository.UpdateCultivateItem(item.Entity);
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ internal interface ICultivationService
|
|||||||
|
|
||||||
ValueTask RemoveCultivateEntryAsync(Guid entryId);
|
ValueTask RemoveCultivateEntryAsync(Guid entryId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移除当前选中养成计划中角色与武器类型的全部养成条目。
|
||||||
|
/// </summary>
|
||||||
|
ValueTask RemoveAvatarAndWeaponEntriesForCurrentProjectAsync();
|
||||||
|
|
||||||
ValueTask RemoveProjectAsync(CultivateProject project);
|
ValueTask RemoveProjectAsync(CultivateProject project);
|
||||||
|
|
||||||
ValueTask<ConsumptionSaveResult> SaveConsumptionAsync(InputConsumption inputConsumption);
|
ValueTask<ConsumptionSaveResult> SaveConsumptionAsync(InputConsumption inputConsumption);
|
||||||
|
|||||||
@@ -77,5 +77,10 @@
|
|||||||
<RadioButton Content="{shuxm:ResourceString Name=ViewDialogCultivationConsumptionSaveStrategyOverwriteExisting}"/>
|
<RadioButton Content="{shuxm:ResourceString Name=ViewDialogCultivationConsumptionSaveStrategyOverwriteExisting}"/>
|
||||||
<RadioButton Content="{shuxm:ResourceString Name=ViewDialogCultivationConsumptionSaveStrategyCreateNewEntry}"/>
|
<RadioButton Content="{shuxm:ResourceString Name=ViewDialogCultivationConsumptionSaveStrategyCreateNewEntry}"/>
|
||||||
</RadioButtons>
|
</RadioButtons>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
Margin="0,13,0,0"
|
||||||
|
Content="{shuxm:ResourceString Name=ViewDialogCultivateBatchClearAvatarAndWeaponEntries}"
|
||||||
|
IsChecked="{x:Bind ClearAvatarAndWeaponEntriesBeforeSync, Mode=TwoWay}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ContentDialog>
|
</ContentDialog>
|
||||||
+2
-1
@@ -10,6 +10,7 @@ using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
|||||||
namespace Snap.Hutao.UI.Xaml.View.Dialog;
|
namespace Snap.Hutao.UI.Xaml.View.Dialog;
|
||||||
|
|
||||||
[DependencyProperty<AvatarPromotionDelta>("PromotionDelta", NotNull = true, CreateDefaultValueCallbackName = nameof(CreatePromotionDeltaDefaultValue))]
|
[DependencyProperty<AvatarPromotionDelta>("PromotionDelta", NotNull = true, CreateDefaultValueCallbackName = nameof(CreatePromotionDeltaDefaultValue))]
|
||||||
|
[DependencyProperty<bool>("ClearAvatarAndWeaponEntriesBeforeSync", DefaultValue = false, NotNull = true)]
|
||||||
internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
|
internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
|
||||||
{
|
{
|
||||||
private readonly IContentDialogFactory contentDialogFactory;
|
private readonly IContentDialogFactory contentDialogFactory;
|
||||||
@@ -45,7 +46,7 @@ internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
|
|||||||
LocalSetting.Set(SettingKeys.CultivationWeapon90LevelTarget, weapon.LevelTarget);
|
LocalSetting.Set(SettingKeys.CultivationWeapon90LevelTarget, weapon.LevelTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new(true, new(PromotionDelta, (ConsumptionSaveStrategyKind)SaveModeSelector.SelectedIndex));
|
return new(true, new CultivatePromotionDeltaOptions(PromotionDelta, (ConsumptionSaveStrategyKind)SaveModeSelector.SelectedIndex, ClearAvatarAndWeaponEntriesBeforeSync));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object CreatePromotionDeltaDefaultValue()
|
private static object CreatePromotionDeltaDefaultValue()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Snap.Hutao.UI.Xaml.View.Dialog;
|
|||||||
|
|
||||||
internal sealed class CultivatePromotionDeltaOptions
|
internal sealed class CultivatePromotionDeltaOptions
|
||||||
{
|
{
|
||||||
public CultivatePromotionDeltaOptions(AvatarPromotionDelta delta, ConsumptionSaveStrategyKind strategy)
|
public CultivatePromotionDeltaOptions(AvatarPromotionDelta delta, ConsumptionSaveStrategyKind strategy, bool clearAvatarAndWeaponEntriesBeforeSync = false)
|
||||||
{
|
{
|
||||||
delta.AvatarLevelTarget = delta.AvatarLevelTarget switch
|
delta.AvatarLevelTarget = delta.AvatarLevelTarget switch
|
||||||
{
|
{
|
||||||
@@ -19,9 +19,15 @@ internal sealed class CultivatePromotionDeltaOptions
|
|||||||
|
|
||||||
Delta = delta;
|
Delta = delta;
|
||||||
Strategy = strategy;
|
Strategy = strategy;
|
||||||
|
ClearAvatarAndWeaponEntriesBeforeSync = clearAvatarAndWeaponEntriesBeforeSync;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AvatarPromotionDelta Delta { get; }
|
public AvatarPromotionDelta Delta { get; }
|
||||||
|
|
||||||
public ConsumptionSaveStrategyKind Strategy { get; }
|
public ConsumptionSaveStrategyKind Strategy { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量同步前是否清空当前计划中已有的角色与武器养成条目(不含家具等其它类型)。
|
||||||
|
/// </summary>
|
||||||
|
public bool ClearAvatarAndWeaponEntriesBeforeSync { get; }
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ using Snap.Hutao.Service.Notification;
|
|||||||
using Snap.Hutao.Service.User;
|
using Snap.Hutao.Service.User;
|
||||||
using Snap.Hutao.UI.Xaml.Control.AutoSuggestBox;
|
using Snap.Hutao.UI.Xaml.Control.AutoSuggestBox;
|
||||||
using Snap.Hutao.UI.Xaml.View.Dialog;
|
using Snap.Hutao.UI.Xaml.View.Dialog;
|
||||||
|
using Snap.Hutao.ViewModel.Cultivation;
|
||||||
using Snap.Hutao.ViewModel.User;
|
using Snap.Hutao.ViewModel.User;
|
||||||
using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
@@ -286,6 +287,11 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
|||||||
BatchCultivateResult result = default;
|
BatchCultivateResult result = default;
|
||||||
using (await scopeContext.ContentDialogFactory.BlockAsync(progressDialog).ConfigureAwait(false))
|
using (await scopeContext.ContentDialogFactory.BlockAsync(progressDialog).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
if (baseline.ClearAvatarAndWeaponEntriesBeforeSync)
|
||||||
|
{
|
||||||
|
await scopeContext.CultivationService.RemoveAvatarAndWeaponEntriesForCurrentProjectAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
ImmutableArray<CalculatorAvatarPromotionDelta>.Builder deltasBuilder = ImmutableArray.CreateBuilder<CalculatorAvatarPromotionDelta>();
|
ImmutableArray<CalculatorAvatarPromotionDelta>.Builder deltasBuilder = ImmutableArray.CreateBuilder<CalculatorAvatarPromotionDelta>();
|
||||||
foreach (AvatarView avatar in targetAvatars)
|
foreach (AvatarView avatar in targetAvatars)
|
||||||
{
|
{
|
||||||
@@ -305,7 +311,7 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
|||||||
|
|
||||||
foreach ((CalculatorConsumption consumption, CalculatorAvatarPromotionDelta delta) in batchConsumption.Items.Zip(deltas))
|
foreach ((CalculatorConsumption consumption, CalculatorAvatarPromotionDelta delta) in batchConsumption.Items.Zip(deltas))
|
||||||
{
|
{
|
||||||
if (!await SaveCultivationAsync(consumption, new(delta, baseline.Strategy), true).ConfigureAwait(false))
|
if (!await SaveCultivationAsync(consumption, new CultivatePromotionDeltaOptions(delta, baseline.Strategy), true).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -314,6 +320,8 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scopeContext.Messenger.Send(CultivationProjectEntriesChangedMessage.Empty);
|
||||||
|
|
||||||
InfoBarMessage message = result.SkippedCount > 0
|
InfoBarMessage message = result.SkippedCount > 0
|
||||||
? InfoBarMessage.Warning(SH.FormatViewModelCultivationBatchAddIncompleted(result.SucceedCount, result.SkippedCount))
|
? InfoBarMessage.Warning(SH.FormatViewModelCultivationBatchAddIncompleted(result.SucceedCount, result.SkippedCount))
|
||||||
: InfoBarMessage.Success(SH.FormatViewModelCultivationBatchAddCompleted(result.SucceedCount, result.SkippedCount));
|
: InfoBarMessage.Success(SH.FormatViewModelCultivationBatchAddCompleted(result.SucceedCount, result.SkippedCount));
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.ViewModel.Cultivation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前养成计划的条目在 UI 外被批量变更(例如从「我的角色」同步)后,通知养成页刷新列表与统计。
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class CultivationProjectEntriesChangedMessage
|
||||||
|
{
|
||||||
|
public static readonly CultivationProjectEntriesChangedMessage Empty = new();
|
||||||
|
|
||||||
|
private CultivationProjectEntriesChangedMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Snap.Hutao.Core;
|
using Snap.Hutao.Core;
|
||||||
using Snap.Hutao.Core.Database;
|
using Snap.Hutao.Core.Database;
|
||||||
@@ -29,7 +30,7 @@ namespace Snap.Hutao.ViewModel.Cultivation;
|
|||||||
[SuppressMessage("", "CA1001")]
|
[SuppressMessage("", "CA1001")]
|
||||||
[BindableCustomPropertyProvider]
|
[BindableCustomPropertyProvider]
|
||||||
[Service(ServiceLifetime.Scoped)]
|
[Service(ServiceLifetime.Scoped)]
|
||||||
internal sealed partial class CultivationViewModel : Abstraction.ViewModel
|
internal sealed partial class CultivationViewModel : Abstraction.ViewModel, IRecipient<CultivationProjectEntriesChangedMessage>
|
||||||
{
|
{
|
||||||
private readonly ExclusiveTokenProvider exclusiveTokenProvider = new();
|
private readonly ExclusiveTokenProvider exclusiveTokenProvider = new();
|
||||||
|
|
||||||
@@ -132,6 +133,17 @@ internal sealed partial class CultivationViewModel : Abstraction.ViewModel
|
|||||||
UpdateEntryCollectionAsync(Projects?.CurrentItem).SafeForget();
|
UpdateEntryCollectionAsync(Projects?.CurrentItem).SafeForget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async void Receive(CultivationProjectEntriesChangedMessage message)
|
||||||
|
{
|
||||||
|
await taskContext.SwitchToMainThreadAsync();
|
||||||
|
if (Projects?.CurrentItem is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await UpdateEntryCollectionAsync(Projects.CurrentItem).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
[Command("AddProjectCommand")]
|
[Command("AddProjectCommand")]
|
||||||
private async Task AddProjectAsync()
|
private async Task AddProjectAsync()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user