mirror of
https://github.com/wangdage12/Snap.Hutao.git
synced 2026-07-31 04:10:25 +08:00
在养成计划,同步所有角色与武器 弹出的 批量添加或更新到当前养成计划 中增加 同步背包物品 ,同步角色信息 (同我的角色,同步角色信息) 两个勾选项
This commit is contained in:
+10
@@ -21,4 +21,14 @@ internal sealed class CultivateProjectAvatarPropertyBatchPreferences
|
|||||||
public int ConsumptionSaveStrategyIndex { get; set; }
|
public int ConsumptionSaveStrategyIndex { get; set; }
|
||||||
|
|
||||||
public bool ClearAvatarAndWeaponEntriesBeforeSync { get; set; }
|
public bool ClearAvatarAndWeaponEntriesBeforeSync { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行批量前是否先通过养成计算器将游戏背包同步到当前计划(与养成计划「同步背包物品」一致)。
|
||||||
|
/// </summary>
|
||||||
|
public bool SyncInventoryItems { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行批量前是否先从米游社原神战绩同步「我的角色」数据(与我的角色「同步角色信息」一致)。
|
||||||
|
/// </summary>
|
||||||
|
public bool SyncCharacterInfo { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
+63
-1
@@ -5,10 +5,17 @@ using Microsoft.UI.Xaml.Controls;
|
|||||||
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;
|
||||||
|
using Snap.Hutao.Model.Entity;
|
||||||
using Snap.Hutao.Model.Entity.Primitive;
|
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.AvatarInfo.Factory;
|
||||||
using Snap.Hutao.Service.Cultivation.Consumption;
|
using Snap.Hutao.Service.Cultivation.Consumption;
|
||||||
using Snap.Hutao.Service.Cultivation.Offline;
|
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.UI.Xaml.View.Dialog;
|
||||||
using Snap.Hutao.ViewModel.AvatarProperty;
|
using Snap.Hutao.ViewModel.AvatarProperty;
|
||||||
using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
||||||
@@ -62,13 +69,66 @@ internal sealed partial class AvatarPropertyBatchCultivateService : IAvatarPrope
|
|||||||
BatchCultivateResult result = default;
|
BatchCultivateResult result = default;
|
||||||
using (await contentDialogFactory.BlockAsync(progressDialog).ConfigureAwait(false))
|
using (await contentDialogFactory.BlockAsync(progressDialog).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
ImmutableArray<AvatarView> avatarsToProcess = targetAvatars;
|
||||||
|
|
||||||
|
if (baseline.SyncCharacterInfo)
|
||||||
|
{
|
||||||
|
IUserService userService = serviceProvider.GetRequiredService<IUserService>();
|
||||||
|
if (await userService.GetCurrentUserAndUidAsync().ConfigureAwait(false) is { } userAndUid)
|
||||||
|
{
|
||||||
|
IServiceScopeFactory scopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
|
||||||
|
using (IServiceScope scope = scopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
IAvatarInfoService avatarInfoService = scope.ServiceProvider.GetRequiredService<IAvatarInfoService>();
|
||||||
|
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<AvatarId> wanted = [.. targetAvatars.Select(static a => a.Id)];
|
||||||
|
ImmutableArray<AvatarView>.Builder filtered = ImmutableArray.CreateBuilder<AvatarView>();
|
||||||
|
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<IMetadataService>();
|
||||||
|
ICultivationMetadataContext cultivationContext = await metadataService
|
||||||
|
.GetContextAsync<CultivationMetadataContext>(cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
IInventoryService inventoryService = serviceProvider.GetRequiredService<IInventoryService>();
|
||||||
|
await inventoryService
|
||||||
|
.RefreshInventoryAsync(RefreshOptions.CreateForWebCalculator(project, cultivationContext))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (baseline.ClearAvatarAndWeaponEntriesBeforeSync)
|
if (baseline.ClearAvatarAndWeaponEntriesBeforeSync)
|
||||||
{
|
{
|
||||||
await cultivationService.RemoveAvatarAndWeaponEntriesForCurrentProjectAsync().ConfigureAwait(false);
|
await 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 avatarsToProcess)
|
||||||
{
|
{
|
||||||
if (!baseline.Delta.TryGetNonErrorCopy(avatar, out CalculatorAvatarPromotionDelta? copy))
|
if (!baseline.Delta.TryGetNonErrorCopy(avatar, out CalculatorAvatarPromotionDelta? copy))
|
||||||
{
|
{
|
||||||
@@ -121,6 +181,8 @@ internal sealed partial class AvatarPropertyBatchCultivateService : IAvatarPrope
|
|||||||
WeaponLevelTarget = d.Weapon?.LevelTarget ?? 90U,
|
WeaponLevelTarget = d.Weapon?.LevelTarget ?? 90U,
|
||||||
ConsumptionSaveStrategyIndex = (int)baseline.Strategy,
|
ConsumptionSaveStrategyIndex = (int)baseline.Strategy,
|
||||||
ClearAvatarAndWeaponEntriesBeforeSync = baseline.ClearAvatarAndWeaponEntriesBeforeSync,
|
ClearAvatarAndWeaponEntriesBeforeSync = baseline.ClearAvatarAndWeaponEntriesBeforeSync,
|
||||||
|
SyncInventoryItems = baseline.SyncInventoryItems,
|
||||||
|
SyncCharacterInfo = baseline.SyncCharacterInfo,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
<x:Double x:Key="SettingsCardWrapThreshold">0</x:Double>
|
<x:Double x:Key="SettingsCardWrapThreshold">0</x:Double>
|
||||||
<x:Double x:Key="SettingsCardWrapNoIconThreshold">0</x:Double>
|
<x:Double x:Key="SettingsCardWrapNoIconThreshold">0</x:Double>
|
||||||
</ContentDialog.Resources>
|
</ContentDialog.Resources>
|
||||||
|
<!-- ScrollViewer:随 ContentDialog 主题高度上限自适应;内容过高时纵向滚动,避免裁切或写死 MaxHeight -->
|
||||||
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||||
<cwc:SettingsCard Header="{shuxm:ResourceString Name=ViewDialogCultivateBatchAvatarLevelTarget}">
|
<cwc:SettingsCard Header="{shuxm:ResourceString Name=ViewDialogCultivateBatchAvatarLevelTarget}">
|
||||||
<NumberBox
|
<NumberBox
|
||||||
@@ -82,5 +84,14 @@
|
|||||||
Margin="0,13,0,0"
|
Margin="0,13,0,0"
|
||||||
Content="{shuxm:ResourceString Name=ViewDialogCultivateBatchClearAvatarAndWeaponEntries}"
|
Content="{shuxm:ResourceString Name=ViewDialogCultivateBatchClearAvatarAndWeaponEntries}"
|
||||||
IsChecked="{x:Bind ClearAvatarAndWeaponEntriesBeforeSync, Mode=TwoWay}"/>
|
IsChecked="{x:Bind ClearAvatarAndWeaponEntriesBeforeSync, Mode=TwoWay}"/>
|
||||||
|
<CheckBox
|
||||||
|
Margin="0,6,0,0"
|
||||||
|
Content="{shuxm:ResourceString Name=ViewPageCultivationRefreshInventory}"
|
||||||
|
IsChecked="{x:Bind SyncInventoryItems, Mode=TwoWay}"/>
|
||||||
|
<CheckBox
|
||||||
|
Margin="0,6,0,0"
|
||||||
|
Content="{shuxm:ResourceString Name=ViewAvatarPropertySyncDataButtonLabel}"
|
||||||
|
IsChecked="{x:Bind SyncCharacterInfo, Mode=TwoWay}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
</ContentDialog>
|
</ContentDialog>
|
||||||
+5
-1
@@ -12,6 +12,8 @@ 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)]
|
[DependencyProperty<bool>("ClearAvatarAndWeaponEntriesBeforeSync", DefaultValue = false, NotNull = true)]
|
||||||
|
[DependencyProperty<bool>("SyncInventoryItems", DefaultValue = false, NotNull = true)]
|
||||||
|
[DependencyProperty<bool>("SyncCharacterInfo", DefaultValue = false, NotNull = true)]
|
||||||
internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
|
internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
|
||||||
{
|
{
|
||||||
private readonly IContentDialogFactory contentDialogFactory;
|
private readonly IContentDialogFactory contentDialogFactory;
|
||||||
@@ -56,7 +58,7 @@ internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
|
|||||||
LocalSetting.Set(SettingKeys.CultivationWeapon90LevelTarget, weapon.LevelTarget);
|
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)
|
private void ApplyInitialPreferences(CultivateProjectAvatarPropertyBatchPreferences p)
|
||||||
@@ -77,6 +79,8 @@ internal sealed partial class CultivatePromotionDeltaBatchDialog : ContentDialog
|
|||||||
|
|
||||||
SaveModeSelector.SelectedIndex = int.Clamp(p.ConsumptionSaveStrategyIndex, 0, 2);
|
SaveModeSelector.SelectedIndex = int.Clamp(p.ConsumptionSaveStrategyIndex, 0, 2);
|
||||||
ClearAvatarAndWeaponEntriesBeforeSync = p.ClearAvatarAndWeaponEntriesBeforeSync;
|
ClearAvatarAndWeaponEntriesBeforeSync = p.ClearAvatarAndWeaponEntriesBeforeSync;
|
||||||
|
SyncInventoryItems = p.SyncInventoryItems;
|
||||||
|
SyncCharacterInfo = p.SyncCharacterInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, bool clearAvatarAndWeaponEntriesBeforeSync = false)
|
public CultivatePromotionDeltaOptions(AvatarPromotionDelta delta, ConsumptionSaveStrategyKind strategy, bool clearAvatarAndWeaponEntriesBeforeSync = false, bool syncInventoryItems = false, bool syncCharacterInfo = false)
|
||||||
{
|
{
|
||||||
delta.AvatarLevelTarget = delta.AvatarLevelTarget switch
|
delta.AvatarLevelTarget = delta.AvatarLevelTarget switch
|
||||||
{
|
{
|
||||||
@@ -20,6 +20,8 @@ internal sealed class CultivatePromotionDeltaOptions
|
|||||||
Delta = delta;
|
Delta = delta;
|
||||||
Strategy = strategy;
|
Strategy = strategy;
|
||||||
ClearAvatarAndWeaponEntriesBeforeSync = clearAvatarAndWeaponEntriesBeforeSync;
|
ClearAvatarAndWeaponEntriesBeforeSync = clearAvatarAndWeaponEntriesBeforeSync;
|
||||||
|
SyncInventoryItems = syncInventoryItems;
|
||||||
|
SyncCharacterInfo = syncCharacterInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AvatarPromotionDelta Delta { get; }
|
public AvatarPromotionDelta Delta { get; }
|
||||||
@@ -30,4 +32,8 @@ internal sealed class CultivatePromotionDeltaOptions
|
|||||||
/// 批量同步前是否清空当前计划中已有的角色与武器养成条目(不含家具等其它类型)。
|
/// 批量同步前是否清空当前计划中已有的角色与武器养成条目(不含家具等其它类型)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ClearAvatarAndWeaponEntriesBeforeSync { get; }
|
public bool ClearAvatarAndWeaponEntriesBeforeSync { get; }
|
||||||
|
|
||||||
|
public bool SyncInventoryItems { get; }
|
||||||
|
|
||||||
|
public bool SyncCharacterInfo { get; }
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user