1
0
mirror of https://github.com/wangdage12/Snap.Hutao.git synced 2026-07-31 04:10:25 +08:00

增加了 背包同步影响所有计划 选项,选择后背包同步将后将更新所有计划的背包数据

This commit is contained in:
mfkvfhpdx
2026-05-04 16:25:53 +08:00
parent 9ea2bb1a6e
commit 82f1820ca9
10 changed files with 70 additions and 9 deletions
@@ -77,6 +77,7 @@ internal static class SettingKeys
public const string CultivationStatisticsMergeUpgradeMaterials = "Snap::Hutao::Cultivation::Statistics::MergeUpgradeMaterials"; public const string CultivationStatisticsMergeUpgradeMaterials = "Snap::Hutao::Cultivation::Statistics::MergeUpgradeMaterials";
public const string CultivationStatisticsTalentSynthCritTenPercent = "Snap::Hutao::Cultivation::Statistics::TalentSynthCritTenPercent"; public const string CultivationStatisticsTalentSynthCritTenPercent = "Snap::Hutao::Cultivation::Statistics::TalentSynthCritTenPercent";
public const string CultivationStatisticsWeeklyBossMaterialInterchange = "Snap::Hutao::Cultivation::Statistics::WeeklyBossMaterialInterchange"; public const string CultivationStatisticsWeeklyBossMaterialInterchange = "Snap::Hutao::Cultivation::Statistics::WeeklyBossMaterialInterchange";
public const string CultivationRefreshInventoryByCalculatorToAllProjects = "Snap::Hutao::Cultivation::RefreshInventory::ByCalculator::ToAllProjects";
// GachaLog // GachaLog
public const string IsEmptyHistoryWishVisible = "Snap::Hutao::GachaLog::HistoryWish::EmptyVisible"; public const string IsEmptyHistoryWishVisible = "Snap::Hutao::GachaLog::HistoryWish::EmptyVisible";
@@ -2465,6 +2465,9 @@ Space Available: {2}</value>
<data name="ViewPageCultivationRefreshInventoryByEmbeddedYae" xml:space="preserve"> <data name="ViewPageCultivationRefreshInventoryByEmbeddedYae" xml:space="preserve">
<value>Sync by Embedded Yae</value> <value>Sync by Embedded Yae</value>
</data> </data>
<data name="ViewPageCultivationRefreshInventoryAllPlansShortLabel" xml:space="preserve">
<value>Inventory sync affects all plans</value>
</data>
<data name="ViewPageCultivationRemoveEntry" xml:space="preserve"> <data name="ViewPageCultivationRemoveEntry" xml:space="preserve">
<value>Delete list</value> <value>Delete list</value>
</data> </data>
@@ -2516,6 +2516,9 @@
<data name="ViewPageCultivationRefreshInventoryByEmbeddedYae" xml:space="preserve"> <data name="ViewPageCultivationRefreshInventoryByEmbeddedYae" xml:space="preserve">
<value>通过 Embedded Yae 同步</value> <value>通过 Embedded Yae 同步</value>
</data> </data>
<data name="ViewPageCultivationRefreshInventoryAllPlansShortLabel" xml:space="preserve">
<value>背包同步影响所有计划</value>
</data>
<data name="ViewPageCultivationRemoveEntry" xml:space="preserve"> <data name="ViewPageCultivationRemoveEntry" xml:space="preserve">
<value>删除清单</value> <value>删除清单</value>
</data> </data>
@@ -2,6 +2,7 @@
// Licensed under the MIT license. // Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Factory.ContentDialog;
using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Calculable;
using Snap.Hutao.Model.Cultivation; using Snap.Hutao.Model.Cultivation;
@@ -117,7 +118,10 @@ internal sealed partial class AvatarPropertyBatchCultivateService : IAvatarPrope
IInventoryService inventoryService = serviceProvider.GetRequiredService<IInventoryService>(); IInventoryService inventoryService = serviceProvider.GetRequiredService<IInventoryService>();
await inventoryService await inventoryService
.RefreshInventoryAsync(RefreshOptions.CreateForWebCalculator(project, cultivationContext)) .RefreshInventoryAsync(RefreshOptions.CreateForWebCalculator(
project,
cultivationContext,
LocalSetting.Get(SettingKeys.CultivationRefreshInventoryByCalculatorToAllProjects, false)))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
} }
@@ -102,6 +102,11 @@ internal sealed partial class CultivationRepository : ICultivationRepository
return this.ObservableCollection<CultivateProject>(); return this.ObservableCollection<CultivateProject>();
} }
public ImmutableArray<Guid> GetCultivateProjectInnerIds()
{
return this.ImmutableArray<CultivateProject, Guid>(query => query.Select(p => p.InnerId));
}
public void RemoveLevelInformationByEntryId(Guid entryId) public void RemoveLevelInformationByEntryId(Guid entryId)
{ {
this.Delete<CultivateEntryLevelInformation>(l => l.EntryId == entryId); this.Delete<CultivateEntryLevelInformation>(l => l.EntryId == entryId);
@@ -27,6 +27,8 @@ internal interface ICultivationRepository : IRepository<CultivateEntryLevelInfor
ObservableCollection<CultivateProject> GetCultivateProjectCollection(); ObservableCollection<CultivateProject> GetCultivateProjectCollection();
ImmutableArray<Guid> GetCultivateProjectInnerIds();
CultivateProject? GetCultivateProjectById(Guid projectId); CultivateProject? GetCultivateProjectById(Guid projectId);
void AddCultivateEntry(CultivateEntry entry); void AddCultivateEntry(CultivateEntry entry);
@@ -23,6 +23,7 @@ internal sealed partial class InventoryService : IInventoryService
private readonly PromotionDeltaFactory promotionDeltaFactory; private readonly PromotionDeltaFactory promotionDeltaFactory;
private readonly IServiceScopeFactory serviceScopeFactory; private readonly IServiceScopeFactory serviceScopeFactory;
private readonly IInventoryRepository inventoryRepository; private readonly IInventoryRepository inventoryRepository;
private readonly ICultivationRepository cultivationRepository;
private readonly IUserService userService; private readonly IUserService userService;
private readonly IMessenger messenger; private readonly IMessenger messenger;
@@ -55,7 +56,7 @@ internal sealed partial class InventoryService : IInventoryService
{ {
case RefreshOptionKind.WebCalculator: case RefreshOptionKind.WebCalculator:
ArgumentNullException.ThrowIfNull(refreshOptions.MetadataContext); ArgumentNullException.ThrowIfNull(refreshOptions.MetadataContext);
return RefreshInventoryByCalculatorAsync(refreshOptions.MetadataContext, refreshOptions.Project); return RefreshInventoryByCalculatorAsync(refreshOptions);
case RefreshOptionKind.EmbeddedYae: case RefreshOptionKind.EmbeddedYae:
ArgumentNullException.ThrowIfNull(refreshOptions.YaeService); ArgumentNullException.ThrowIfNull(refreshOptions.YaeService);
ArgumentNullException.ThrowIfNull(refreshOptions.ViewModelSupportLaunchExecution); ArgumentNullException.ThrowIfNull(refreshOptions.ViewModelSupportLaunchExecution);
@@ -71,8 +72,12 @@ internal sealed partial class InventoryService : IInventoryService
inventoryRepository.RemoveInventoryItemRangeByProjectId(projectId); 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) if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is not { } userAndUid)
{ {
messenger.Send(InfoBarMessage.Warning(SH.MustSelectUserAndUid)); messenger.Send(InfoBarMessage.Warning(SH.MustSelectUserAndUid));
@@ -98,8 +103,25 @@ internal sealed partial class InventoryService : IInventoryService
if (batchConsumption is { OverallConsume: { IsDefault: false } items }) if (batchConsumption is { OverallConsume: { IsDefault: false } items })
{ {
inventoryRepository.RemoveInventoryItemRangeByProjectId(project.InnerId); static IEnumerable<InventoryItem> ToInventoryItems(ImmutableArray<Item> consumeItems, Guid projectId)
inventoryRepository.AddInventoryItemRangeByProjectId(items.SelectAsArray(static (item, project) => InventoryItem.From(project.InnerId, item.Id, (uint)((int)item.Num - item.LackNum)), project)); {
return consumeItems.SelectAsArray(static (item, pid) => InventoryItem.From(pid, item.Id, (uint)((int)item.Num - item.LackNum)), projectId);
}
if (syncToAllProjects)
{
ImmutableArray<Guid> 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));
}
} }
} }
@@ -24,7 +24,12 @@ internal sealed class RefreshOptions
public required IViewModelSupportLaunchExecution? ViewModelSupportLaunchExecution { get; init; } public required IViewModelSupportLaunchExecution? ViewModelSupportLaunchExecution { get; init; }
public static RefreshOptions CreateForWebCalculator(CultivateProject project, ICultivationMetadataContext context) /// <summary>
/// 通过养成计算器同步背包时,是否将结果写入所有养成计划(否则仅当前计划)。
/// </summary>
public bool SyncCalculatorInventoryToAllProjects { get; init; }
public static RefreshOptions CreateForWebCalculator(CultivateProject project, ICultivationMetadataContext context, bool syncCalculatorInventoryToAllProjects = false)
{ {
return new() return new()
{ {
@@ -33,6 +38,7 @@ internal sealed class RefreshOptions
MetadataContext = context, MetadataContext = context,
YaeService = default, YaeService = default,
ViewModelSupportLaunchExecution = default, ViewModelSupportLaunchExecution = default,
SyncCalculatorInventoryToAllProjects = syncCalculatorInventoryToAllProjects,
}; };
} }
@@ -471,7 +471,9 @@
Command="{Binding SyncAllAvatarsAndWeaponsCommand}" Command="{Binding SyncAllAvatarsAndWeaponsCommand}"
Icon="{shuxm:FontIcon Glyph=&#xE72C;}" Icon="{shuxm:FontIcon Glyph=&#xE72C;}"
Label="{shuxm:ResourceString Name=ViewPageCultivationSyncAllAvatarsAndWeapons}"/> Label="{shuxm:ResourceString Name=ViewPageCultivationSyncAllAvatarsAndWeapons}"/>
<AppBarButton Icon="{shuxm:FontIcon Glyph=&#xE895;}" Label="{shuxm:ResourceString Name=ViewPageCultivationRefreshInventory}"> <AppBarButton
Icon="{shuxm:FontIcon Glyph=&#xE895;}"
Label="{shuxm:ResourceString Name=ViewPageCultivationRefreshInventory}">
<AppBarButton.Flyout> <AppBarButton.Flyout>
<MenuFlyout Placement="BottomEdgeAlignedRight"> <MenuFlyout Placement="BottomEdgeAlignedRight">
<MenuFlyoutItem <MenuFlyoutItem
@@ -485,6 +487,10 @@
</MenuFlyout> </MenuFlyout>
</AppBarButton.Flyout> </AppBarButton.Flyout>
</AppBarButton> </AppBarButton>
<AppBarToggleButton
Icon="{shuxm:FontIcon Glyph=&#xE8B7;}"
IsChecked="{Binding SyncInventoryByCalculatorToAllProjects, Mode=TwoWay}"
Label="{shuxm:ResourceString Name=ViewPageCultivationRefreshInventoryAllPlansShortLabel}"/>
<AppBarButton <AppBarButton
Command="{Binding AddProjectCommand}" Command="{Binding AddProjectCommand}"
Icon="{shuxm:FontIcon Glyph=&#xE710;}" Icon="{shuxm:FontIcon Glyph=&#xE710;}"
@@ -733,7 +739,6 @@
</Style> </Style>
</GridView.ItemContainerStyle> </GridView.ItemContainerStyle>
</GridView> </GridView>
</Border> </Border>
</Border> </Border>
</PivotItem> </PivotItem>
@@ -89,6 +89,9 @@ internal sealed partial class CultivationViewModel : Abstraction.ViewModel, IRec
[ObservableProperty] [ObservableProperty]
public partial bool WeeklyBossMaterialInterchange { get; set; } = LocalSetting.Get(SettingKeys.CultivationStatisticsWeeklyBossMaterialInterchange, false); public partial bool WeeklyBossMaterialInterchange { get; set; } = LocalSetting.Get(SettingKeys.CultivationStatisticsWeeklyBossMaterialInterchange, false);
[ObservableProperty]
public partial bool SyncInventoryByCalculatorToAllProjects { get; set; } = LocalSetting.Get(SettingKeys.CultivationRefreshInventoryByCalculatorToAllProjects, false);
[ObservableProperty] [ObservableProperty]
public partial ObservableCollection<StatisticsCultivateItem>? StatisticsItems { get; set; } public partial ObservableCollection<StatisticsCultivateItem>? StatisticsItems { get; set; }
@@ -141,6 +144,11 @@ internal sealed partial class CultivationViewModel : Abstraction.ViewModel, IRec
UpdateEntryCollectionAsync(Projects?.CurrentItem).SafeForget(); UpdateEntryCollectionAsync(Projects?.CurrentItem).SafeForget();
} }
partial void OnSyncInventoryByCalculatorToAllProjectsChanged(bool value)
{
LocalSetting.Set(SettingKeys.CultivationRefreshInventoryByCalculatorToAllProjects, value);
}
public async void Receive(CultivationProjectEntriesChangedMessage message) public async void Receive(CultivationProjectEntriesChangedMessage message)
{ {
await taskContext.SwitchToMainThreadAsync(); await taskContext.SwitchToMainThreadAsync();
@@ -322,7 +330,9 @@ internal sealed partial class CultivationViewModel : Abstraction.ViewModel, IRec
using (await contentDialogFactory.BlockAsync(dialog).ConfigureAwait(false)) 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 UpdateInventoryItemsAsync().ConfigureAwait(false);
await UpdateStatisticsItemsAsync().ConfigureAwait(false); await UpdateStatisticsItemsAsync().ConfigureAwait(false);