diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs b/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs index 7e65fd9..03c48ee 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs @@ -77,6 +77,7 @@ internal static class SettingKeys public const string CultivationStatisticsMergeUpgradeMaterials = "Snap::Hutao::Cultivation::Statistics::MergeUpgradeMaterials"; public const string CultivationStatisticsTalentSynthCritTenPercent = "Snap::Hutao::Cultivation::Statistics::TalentSynthCritTenPercent"; public const string CultivationStatisticsWeeklyBossMaterialInterchange = "Snap::Hutao::Cultivation::Statistics::WeeklyBossMaterialInterchange"; + public const string CultivationRefreshInventoryByCalculatorToAllProjects = "Snap::Hutao::Cultivation::RefreshInventory::ByCalculator::ToAllProjects"; // GachaLog public const string IsEmptyHistoryWishVisible = "Snap::Hutao::GachaLog::HistoryWish::EmptyVisible"; diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx index 4190042..b0dcc29 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx @@ -2465,6 +2465,9 @@ Space Available: {2} Sync by Embedded Yae + + Inventory sync affects all plans + Delete list diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index 9b55ffb..b0fc331 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -2516,6 +2516,9 @@ 通过 Embedded Yae 同步 + + 背包同步影响所有计划 + 删除清单 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/AvatarPropertyBatchCultivateService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/AvatarPropertyBatchCultivateService.cs index b017724..bdb87d6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/AvatarPropertyBatchCultivateService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/AvatarPropertyBatchCultivateService.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Core.Setting; using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Cultivation; @@ -117,7 +118,10 @@ internal sealed partial class AvatarPropertyBatchCultivateService : IAvatarPrope IInventoryService inventoryService = serviceProvider.GetRequiredService(); await inventoryService - .RefreshInventoryAsync(RefreshOptions.CreateForWebCalculator(project, cultivationContext)) + .RefreshInventoryAsync(RefreshOptions.CreateForWebCalculator( + project, + cultivationContext, + LocalSetting.Get(SettingKeys.CultivationRefreshInventoryByCalculatorToAllProjects, false))) .ConfigureAwait(false); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationRepository.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationRepository.cs index b7eda10..33c87ea 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationRepository.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/CultivationRepository.cs @@ -102,6 +102,11 @@ internal sealed partial class CultivationRepository : ICultivationRepository return this.ObservableCollection(); } + public ImmutableArray GetCultivateProjectInnerIds() + { + return this.ImmutableArray(query => query.Select(p => p.InnerId)); + } + public void RemoveLevelInformationByEntryId(Guid entryId) { this.Delete(l => l.EntryId == entryId); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationRepository.cs b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationRepository.cs index 7a9454e..328d499 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationRepository.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Cultivation/ICultivationRepository.cs @@ -27,6 +27,8 @@ internal interface ICultivationRepository : IRepository GetCultivateProjectCollection(); + ImmutableArray GetCultivateProjectInnerIds(); + CultivateProject? GetCultivateProjectById(Guid projectId); void AddCultivateEntry(CultivateEntry entry); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Inventory/InventoryService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Inventory/InventoryService.cs index 6c5036d..710a45e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Inventory/InventoryService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Inventory/InventoryService.cs @@ -23,6 +23,7 @@ internal sealed partial class InventoryService : IInventoryService private readonly PromotionDeltaFactory promotionDeltaFactory; private readonly IServiceScopeFactory serviceScopeFactory; private readonly IInventoryRepository inventoryRepository; + private readonly ICultivationRepository cultivationRepository; private readonly IUserService userService; private readonly IMessenger messenger; @@ -55,7 +56,7 @@ internal sealed partial class InventoryService : IInventoryService { case RefreshOptionKind.WebCalculator: ArgumentNullException.ThrowIfNull(refreshOptions.MetadataContext); - return RefreshInventoryByCalculatorAsync(refreshOptions.MetadataContext, refreshOptions.Project); + return RefreshInventoryByCalculatorAsync(refreshOptions); case RefreshOptionKind.EmbeddedYae: ArgumentNullException.ThrowIfNull(refreshOptions.YaeService); ArgumentNullException.ThrowIfNull(refreshOptions.ViewModelSupportLaunchExecution); @@ -71,8 +72,12 @@ internal sealed partial class InventoryService : IInventoryService inventoryRepository.RemoveInventoryItemRangeByProjectId(projectId); } - private async ValueTask RefreshInventoryByCalculatorAsync(ICultivationMetadataContext context, CultivateProject project) + private async ValueTask RefreshInventoryByCalculatorAsync(RefreshOptions options) { + ICultivationMetadataContext context = options.MetadataContext!; + CultivateProject project = options.Project; + bool syncToAllProjects = options.SyncCalculatorInventoryToAllProjects; + if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is not { } userAndUid) { messenger.Send(InfoBarMessage.Warning(SH.MustSelectUserAndUid)); @@ -98,8 +103,25 @@ internal sealed partial class InventoryService : IInventoryService if (batchConsumption is { OverallConsume: { IsDefault: false } items }) { - inventoryRepository.RemoveInventoryItemRangeByProjectId(project.InnerId); - inventoryRepository.AddInventoryItemRangeByProjectId(items.SelectAsArray(static (item, project) => InventoryItem.From(project.InnerId, item.Id, (uint)((int)item.Num - item.LackNum)), project)); + static IEnumerable ToInventoryItems(ImmutableArray consumeItems, Guid projectId) + { + return consumeItems.SelectAsArray(static (item, pid) => InventoryItem.From(pid, item.Id, (uint)((int)item.Num - item.LackNum)), projectId); + } + + if (syncToAllProjects) + { + ImmutableArray projectIds = cultivationRepository.GetCultivateProjectInnerIds(); + foreach (Guid projectId in projectIds.AsSpan()) + { + inventoryRepository.RemoveInventoryItemRangeByProjectId(projectId); + inventoryRepository.AddInventoryItemRangeByProjectId(ToInventoryItems(items, projectId)); + } + } + else + { + inventoryRepository.RemoveInventoryItemRangeByProjectId(project.InnerId); + inventoryRepository.AddInventoryItemRangeByProjectId(ToInventoryItems(items, project.InnerId)); + } } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Inventory/RefreshOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Inventory/RefreshOptions.cs index 19c4e69..e4bc705 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Inventory/RefreshOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Inventory/RefreshOptions.cs @@ -24,7 +24,12 @@ internal sealed class RefreshOptions public required IViewModelSupportLaunchExecution? ViewModelSupportLaunchExecution { get; init; } - public static RefreshOptions CreateForWebCalculator(CultivateProject project, ICultivationMetadataContext context) + /// + /// 通过养成计算器同步背包时,是否将结果写入所有养成计划(否则仅当前计划)。 + /// + public bool SyncCalculatorInventoryToAllProjects { get; init; } + + public static RefreshOptions CreateForWebCalculator(CultivateProject project, ICultivationMetadataContext context, bool syncCalculatorInventoryToAllProjects = false) { return new() { @@ -33,6 +38,7 @@ internal sealed class RefreshOptions MetadataContext = context, YaeService = default, ViewModelSupportLaunchExecution = default, + SyncCalculatorInventoryToAllProjects = syncCalculatorInventoryToAllProjects, }; } diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/CultivationPage.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/CultivationPage.xaml index 2e87130..083c9a2 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/CultivationPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/CultivationPage.xaml @@ -471,7 +471,9 @@ Command="{Binding SyncAllAvatarsAndWeaponsCommand}" Icon="{shuxm:FontIcon Glyph=}" Label="{shuxm:ResourceString Name=ViewPageCultivationSyncAllAvatarsAndWeapons}"/> - + + - diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Cultivation/CultivationViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Cultivation/CultivationViewModel.cs index 8c16b39..1f5b587 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Cultivation/CultivationViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Cultivation/CultivationViewModel.cs @@ -89,6 +89,9 @@ internal sealed partial class CultivationViewModel : Abstraction.ViewModel, IRec [ObservableProperty] public partial bool WeeklyBossMaterialInterchange { get; set; } = LocalSetting.Get(SettingKeys.CultivationStatisticsWeeklyBossMaterialInterchange, false); + [ObservableProperty] + public partial bool SyncInventoryByCalculatorToAllProjects { get; set; } = LocalSetting.Get(SettingKeys.CultivationRefreshInventoryByCalculatorToAllProjects, false); + [ObservableProperty] public partial ObservableCollection? StatisticsItems { get; set; } @@ -141,6 +144,11 @@ internal sealed partial class CultivationViewModel : Abstraction.ViewModel, IRec UpdateEntryCollectionAsync(Projects?.CurrentItem).SafeForget(); } + partial void OnSyncInventoryByCalculatorToAllProjectsChanged(bool value) + { + LocalSetting.Set(SettingKeys.CultivationRefreshInventoryByCalculatorToAllProjects, value); + } + public async void Receive(CultivationProjectEntriesChangedMessage message) { await taskContext.SwitchToMainThreadAsync(); @@ -322,7 +330,9 @@ internal sealed partial class CultivationViewModel : Abstraction.ViewModel, IRec using (await contentDialogFactory.BlockAsync(dialog).ConfigureAwait(false)) { - await inventoryService.RefreshInventoryAsync(RefreshOptions.CreateForWebCalculator(Projects.CurrentItem, metadataContext)).ConfigureAwait(false); + await inventoryService + .RefreshInventoryAsync(RefreshOptions.CreateForWebCalculator(Projects.CurrentItem, metadataContext, SyncInventoryByCalculatorToAllProjects)) + .ConfigureAwait(false); await UpdateInventoryItemsAsync().ConfigureAwait(false); await UpdateStatisticsItemsAsync().ConfigureAwait(false);