From 3db52e81847a006196e8d57a357a7238e0b2bcfd Mon Sep 17 00:00:00 2001
From: DismissedLight <1686188646@qq.com>
Date: Sun, 17 Sep 2023 16:05:10 +0800
Subject: [PATCH] spiral abyss rework
---
.../Identity/IdentityGenerator.cs | 6 ++
src/Snap.Hutao/Snap.Hutao/App.xaml | 2 +-
src/Snap.Hutao/Snap.Hutao/Control/Loading.cs | 2 +-
.../EnumerableExtension.Collection.cs | 27 ++++----
.../Model/Entity/SpiralAbyssEntry.cs | 10 ---
.../Resource/Localization/SH.Designer.cs | 8 +--
.../Snap.Hutao/Resource/Localization/SH.resx | 8 +--
.../Metadata/IMetadataServiceIdDataMap.cs | 10 +++
.../Metadata/MetadataService.Indexing.cs | 32 +++++++++
.../ISpiralAbyssRecordDbService.cs | 2 +-
.../SpiralAbyss/ISpiralAbyssRecordService.cs | 5 +-
.../SpiralAbyss/SpiralAbyssRecordDbService.cs | 7 +-
.../SpiralAbyss/SpiralAbyssRecordService.cs | 65 +++++++++++++++----
.../Snap.Hutao/View/Page/AchievementPage.xaml | 7 +-
.../View/Page/SpiralAbyssRecordPage.xaml | 49 ++++++++------
.../SpiralAbyss/SpiralAbyssMetadataContext.cs | 22 +++++++
.../SpiralAbyss/SpiralAbyssRecordViewModel.cs | 47 ++++----------
.../ViewModel/SpiralAbyss/SpiralAbyssView.cs | 50 +++++++++++---
18 files changed, 239 insertions(+), 120 deletions(-)
create mode 100644 src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssMetadataContext.cs
diff --git a/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Identity/IdentityGenerator.cs b/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Identity/IdentityGenerator.cs
index 26de90b7..a3440e94 100644
--- a/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Identity/IdentityGenerator.cs
+++ b/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Identity/IdentityGenerator.cs
@@ -89,6 +89,12 @@ internal sealed class IdentityGenerator : IIncrementalGenerator
{
return Value.GetHashCode();
}
+
+ ///
+ public override string ToString()
+ {
+ return Value.ToString();
+ }
}
""");
diff --git a/src/Snap.Hutao/Snap.Hutao/App.xaml b/src/Snap.Hutao/Snap.Hutao/App.xaml
index 84305f5c..a4d22ee8 100644
--- a/src/Snap.Hutao/Snap.Hutao/App.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/App.xaml
@@ -2,8 +2,8 @@
x:Class="Snap.Hutao.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:cwcw="using:CommunityToolkit.WinUI.Controls"
xmlns:cwc="using:CommunityToolkit.WinUI.Converters"
+ xmlns:cwcw="using:CommunityToolkit.WinUI.Controls"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:shci="using:Snap.Hutao.Control.Image"
xmlns:shmmc="using:Snap.Hutao.Model.Metadata.Converter"
diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Loading.cs b/src/Snap.Hutao/Snap.Hutao/Control/Loading.cs
index b35da832..bb443a05 100644
--- a/src/Snap.Hutao/Snap.Hutao/Control/Loading.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Control/Loading.cs
@@ -9,7 +9,7 @@ namespace Snap.Hutao.Control;
[TemplateVisualState(Name = "LoadingOut", GroupName = "CommonStates")]
internal class Loading : Microsoft.UI.Xaml.Controls.ContentControl
{
- private static readonly DependencyProperty IsLoadingProperty = DependencyProperty.Register(nameof(IsLoading), typeof(bool), typeof(Loading), new PropertyMetadata(default(bool), IsLoadingPropertyChanged));
+ public static readonly DependencyProperty IsLoadingProperty = DependencyProperty.Register(nameof(IsLoading), typeof(bool), typeof(Loading), new PropertyMetadata(default(bool), IsLoadingPropertyChanged));
private FrameworkElement? presenter;
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.Collection.cs b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.Collection.cs
index 50acd5fc..934f6be5 100644
--- a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.Collection.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.Collection.cs
@@ -11,20 +11,6 @@ namespace Snap.Hutao.Extension;
///
internal static partial class EnumerableExtension
{
- ///
- /// 尝试添加物品
- ///
- /// 物品类型
- /// 集合
- /// 物品
- public static void AddIfNotContains(this Collection collection, T item)
- {
- if (!collection.Contains(item))
- {
- collection.Add(item);
- }
- }
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNullOrEmpty([NotNullWhen(false)][MaybeNullWhen(true)] this Collection? source)
{
@@ -57,4 +43,17 @@ internal static partial class EnumerableExtension
return count;
}
+
+ public static int FirstIndexOf(this Collection collection, Func predicate)
+ {
+ for (int index = 0; index < collection.Count; index++)
+ {
+ if (predicate(collection[index]))
+ {
+ return index;
+ }
+ }
+
+ return -1;
+ }
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs
index ad52f3b8..4b4e3aef 100644
--- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs
@@ -59,14 +59,4 @@ internal sealed class SpiralAbyssEntry : ObservableObject,
SpiralAbyss = spiralAbyss,
};
}
-
- ///
- /// 更新深渊信息
- ///
- /// 深渊信息
- public void UpdateSpiralAbyss(Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss spiralAbyss)
- {
- SpiralAbyss = spiralAbyss;
- OnPropertyChanged(nameof(SpiralAbyss));
- }
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs
index 2a5f979f..047429df 100644
--- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs
@@ -862,7 +862,7 @@ namespace Snap.Hutao.Resource.Localization {
}
///
- /// 查找类似 打怪 的本地化字符串。
+ /// 查找类似 击败怪物 的本地化字符串。
///
internal static string ModelMetadataTowerGoalTypeDefeatMonsters {
get {
@@ -871,7 +871,7 @@ namespace Snap.Hutao.Resource.Localization {
}
///
- /// 查找类似 守塔 的本地化字符串。
+ /// 查找类似 守护目标 的本地化字符串。
///
internal static string ModelMetadataTowerGoalTypeDefendTarget {
get {
@@ -880,7 +880,7 @@ namespace Snap.Hutao.Resource.Localization {
}
///
- /// 查找类似 附加 的本地化字符串。
+ /// 查找类似 附加:增援怪物 的本地化字符串。
///
internal static string ModelMetadataTowerWaveTypeAdditional {
get {
@@ -1060,7 +1060,7 @@ namespace Snap.Hutao.Resource.Localization {
}
///
- /// 查找类似 第一波附加:为第一波补充怪物 的本地化字符串。
+ /// 查找类似 第一波附加:增援第一波怪物 的本地化字符串。
///
internal static string ModelMetadataTowerWaveTypeWave1Additional {
get {
diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
index eaa6b75d..b466351e 100644
--- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
+++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
@@ -414,13 +414,13 @@
Need EXACT same string in game
- 打怪
+ 击败怪物
- 守塔
+ 守护目标
- 附加
+ 附加:增援怪物
A组:不同的组同时在场,各自分波独立
@@ -480,7 +480,7 @@
第一波:击败所有怪物,下一波才会出现
- 第一波附加:为第一波补充怪物
+ 第一波附加:增援第一波怪物
第二波:击败所有怪物,下一波才会出现
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/IMetadataServiceIdDataMap.cs b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/IMetadataServiceIdDataMap.cs
index c9a0fc28..b7dcd248 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/IMetadataServiceIdDataMap.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/IMetadataServiceIdDataMap.cs
@@ -4,7 +4,9 @@
using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Model.Metadata.Avatar;
using Snap.Hutao.Model.Metadata.Item;
+using Snap.Hutao.Model.Metadata.Monster;
using Snap.Hutao.Model.Metadata.Reliquary;
+using Snap.Hutao.Model.Metadata.Tower;
using Snap.Hutao.Model.Metadata.Weapon;
using Snap.Hutao.Model.Primitive;
@@ -70,10 +72,18 @@ internal interface IMetadataServiceIdDataMap
/// 字典
ValueTask> GetIdToReliquaryMainPropertyMapAsync(CancellationToken token = default);
+ ValueTask> GetIdToTowerScheduleMapAsync(CancellationToken token = default);
+
///
/// 异步获取ID到武器的字典
///
/// 取消令牌
/// Id到武器的字典
ValueTask> GetIdToWeaponMapAsync(CancellationToken token = default);
+
+ ValueTask>> GetGroupIdToTowerLevelGroupMapAsync(CancellationToken token = default);
+
+ ValueTask> GetIdToTowerFloorMapAsync(CancellationToken token = default);
+
+ ValueTask> GetRelationshipIdToMonsterMapAsync(CancellationToken token = default);
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs
index 2276cd28..f6b0c259 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs
@@ -6,7 +6,9 @@ using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Model.Metadata;
using Snap.Hutao.Model.Metadata.Avatar;
using Snap.Hutao.Model.Metadata.Item;
+using Snap.Hutao.Model.Metadata.Monster;
using Snap.Hutao.Model.Metadata.Reliquary;
+using Snap.Hutao.Model.Metadata.Tower;
using Snap.Hutao.Model.Metadata.Weapon;
using Snap.Hutao.Model.Primitive;
@@ -41,6 +43,21 @@ internal sealed partial class MetadataService
return memoryCache.Set(cacheKey, dict);
}
+ public async ValueTask>> GetGroupIdToTowerLevelGroupMapAsync(CancellationToken token = default)
+ {
+ string cacheKey = $"{nameof(MetadataService)}.Cache.{FileNameTowerLevel}.Map.Group.{nameof(TowerLevelGroupId)}";
+
+ if (memoryCache.TryGetValue(cacheKey, out object? value))
+ {
+ ArgumentNullException.ThrowIfNull(value);
+ return (Dictionary>)value;
+ }
+
+ List list = await FromCacheOrFileAsync>(FileNameTowerLevel, token).ConfigureAwait(false);
+ Dictionary> dict = list.GroupBy(l => l.GroupId).ToDictionary(g => g.Key, g => g.ToList());
+ return memoryCache.Set(cacheKey, dict);
+ }
+
///
public ValueTask> GetIdToAchievementMapAsync(CancellationToken token = default)
{
@@ -102,6 +119,16 @@ internal sealed partial class MetadataService
return FromCacheAsDictionaryAsync(FileNameReliquaryMainAffix, r => r.Id, r => r.Type, token);
}
+ public ValueTask> GetIdToTowerFloorMapAsync(CancellationToken token = default)
+ {
+ return FromCacheAsDictionaryAsync(FileNameTowerFloor, t => t.Id, token);
+ }
+
+ public ValueTask> GetIdToTowerScheduleMapAsync(CancellationToken token = default)
+ {
+ return FromCacheAsDictionaryAsync(FileNameTowerSchedule, t => t.Id, token);
+ }
+
///
public ValueTask> GetIdToWeaponMapAsync(CancellationToken token = default)
{
@@ -126,6 +153,11 @@ internal sealed partial class MetadataService
return FromCacheAsDictionaryAsync, GrowCurve>(FileNameWeaponCurve, w => w.Level, w => w.Map, token);
}
+ public ValueTask> GetRelationshipIdToMonsterMapAsync(CancellationToken token = default)
+ {
+ return FromCacheAsDictionaryAsync(FileNameMonster, m => m.RelationshipId, token);
+ }
+
///
public ValueTask> GetNameToAvatarMapAsync(CancellationToken token = default)
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/ISpiralAbyssRecordDbService.cs b/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/ISpiralAbyssRecordDbService.cs
index 6cdcd94c..097280ee 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/ISpiralAbyssRecordDbService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/ISpiralAbyssRecordDbService.cs
@@ -10,7 +10,7 @@ internal interface ISpiralAbyssRecordDbService
{
ValueTask AddSpiralAbyssEntryAsync(SpiralAbyssEntry entry);
- ValueTask> GetSpiralAbyssEntryCollectionByUidAsync(string uid);
+ ValueTask> GetSpiralAbyssEntryListByUidAsync(string uid);
ValueTask UpdateSpiralAbyssEntryAsync(SpiralAbyssEntry entry);
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/ISpiralAbyssRecordService.cs b/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/ISpiralAbyssRecordService.cs
index 52090398..3fcf4a4b 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/ISpiralAbyssRecordService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/ISpiralAbyssRecordService.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Snap.Hutao.Model.Entity;
+using Snap.Hutao.ViewModel.SpiralAbyss;
using Snap.Hutao.ViewModel.User;
using System.Collections.ObjectModel;
@@ -18,7 +19,9 @@ internal interface ISpiralAbyssRecordService
///
/// 当前角色
/// 深渊记录集合
- ValueTask> GetSpiralAbyssCollectionAsync(UserAndUid userAndUid);
+ ValueTask> GetSpiralAbyssViewCollectionAsync(UserAndUid userAndUid);
+
+ ValueTask InitializeAsync();
///
/// 异步刷新深渊记录
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordDbService.cs b/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordDbService.cs
index 2cdd5ef4..668cb07a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordDbService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordDbService.cs
@@ -15,19 +15,16 @@ internal sealed partial class SpiralAbyssRecordDbService : ISpiralAbyssRecordDbS
{
private readonly IServiceProvider serviceProvider;
- public async ValueTask> GetSpiralAbyssEntryCollectionByUidAsync(string uid)
+ public async ValueTask> GetSpiralAbyssEntryListByUidAsync(string uid)
{
using (IServiceScope scope = serviceProvider.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
-
- List entries = await appDbContext.SpiralAbysses
+ return await appDbContext.SpiralAbysses
.Where(s => s.Uid == uid)
.OrderByDescending(s => s.ScheduleId)
.ToListAsync()
.ConfigureAwait(false);
-
- return entries.ToObservableCollection();
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordService.cs b/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordService.cs
index ba71507f..fe791ab4 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/SpiralAbyss/SpiralAbyssRecordService.cs
@@ -3,6 +3,10 @@
using Snap.Hutao.Core.DependencyInjection.Abstraction;
using Snap.Hutao.Model.Entity;
+using Snap.Hutao.Model.Metadata;
+using Snap.Hutao.Model.Primitive;
+using Snap.Hutao.Service.Metadata;
+using Snap.Hutao.ViewModel.SpiralAbyss;
using Snap.Hutao.ViewModel.User;
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
using Snap.Hutao.Web.Response;
@@ -18,15 +22,35 @@ namespace Snap.Hutao.Service.SpiralAbyss;
[Injection(InjectAs.Scoped, typeof(ISpiralAbyssRecordService))]
internal sealed partial class SpiralAbyssRecordService : ISpiralAbyssRecordService
{
- private readonly ITaskContext taskContext;
private readonly IOverseaSupportFactory gameRecordClientFactory;
private readonly ISpiralAbyssRecordDbService spiralAbyssRecordDbService;
+ private readonly IMetadataService metadataService;
+ private readonly ITaskContext taskContext;
private string? uid;
- private ObservableCollection? spiralAbysses;
+ private ObservableCollection? spiralAbysses;
+ private SpiralAbyssMetadataContext? metadataContext;
+
+ public async ValueTask InitializeAsync()
+ {
+ if (await metadataService.InitializeAsync().ConfigureAwait(false))
+ {
+ metadataContext = new()
+ {
+ IdScheduleMap = await metadataService.GetIdToTowerScheduleMapAsync().ConfigureAwait(false),
+ IdFloorMap = await metadataService.GetIdToTowerFloorMapAsync().ConfigureAwait(false),
+ IdLevelGroupMap = await metadataService.GetGroupIdToTowerLevelGroupMapAsync().ConfigureAwait(false),
+ IdMonsterMap = await metadataService.GetRelationshipIdToMonsterMapAsync().ConfigureAwait(false),
+ IdAvatarMap = AvatarIds.WithPlayers(await metadataService.GetIdToAvatarMapAsync().ConfigureAwait(false)),
+ };
+ return true;
+ }
+
+ return false;
+ }
///
- public async ValueTask> GetSpiralAbyssCollectionAsync(UserAndUid userAndUid)
+ public async ValueTask> GetSpiralAbyssViewCollectionAsync(UserAndUid userAndUid)
{
if (uid != userAndUid.Uid.Value)
{
@@ -34,9 +58,15 @@ internal sealed partial class SpiralAbyssRecordService : ISpiralAbyssRecordServi
}
uid = userAndUid.Uid.Value;
- spiralAbysses ??= await spiralAbyssRecordDbService
- .GetSpiralAbyssEntryCollectionByUidAsync(userAndUid.Uid.Value)
- .ConfigureAwait(false);
+ if (spiralAbysses is null)
+ {
+ List list = await spiralAbyssRecordDbService
+ .GetSpiralAbyssEntryListByUidAsync(userAndUid.Uid.Value)
+ .ConfigureAwait(false);
+
+ ArgumentNullException.ThrowIfNull(metadataContext);
+ spiralAbysses = list.SelectList(entity => SpiralAbyssView.From(entity, metadataContext)).ToObservableCollection();
+ }
return spiralAbysses;
}
@@ -44,6 +74,11 @@ internal sealed partial class SpiralAbyssRecordService : ISpiralAbyssRecordServi
///
public async ValueTask RefreshSpiralAbyssAsync(UserAndUid userAndUid)
{
+ // request the index first
+ await gameRecordClientFactory
+ .Create(userAndUid.User.IsOversea)
+ .GetPlayerInfoAsync(userAndUid)
+ .ConfigureAwait(false);
await RefreshSpiralAbyssCoreAsync(userAndUid, SpiralAbyssSchedule.Last).ConfigureAwait(false);
await RefreshSpiralAbyssCoreAsync(userAndUid, SpiralAbyssSchedule.Current).ConfigureAwait(false);
}
@@ -60,20 +95,26 @@ internal sealed partial class SpiralAbyssRecordService : ISpiralAbyssRecordServi
Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss webSpiralAbyss = response.Data;
ArgumentNullException.ThrowIfNull(spiralAbysses);
- if (spiralAbysses.SingleOrDefault(s => s.ScheduleId == webSpiralAbyss.ScheduleId) is { } existEntry)
- {
- await taskContext.SwitchToMainThreadAsync();
- existEntry.UpdateSpiralAbyss(webSpiralAbyss);
+ ArgumentNullException.ThrowIfNull(metadataContext);
+ int index = spiralAbysses.FirstIndexOf(s => s.Entity.ScheduleId == webSpiralAbyss.ScheduleId);
+ if (index > 0)
+ {
await taskContext.SwitchToBackgroundAsync();
- await spiralAbyssRecordDbService.UpdateSpiralAbyssEntryAsync(existEntry).ConfigureAwait(false);
+ SpiralAbyssView view = spiralAbysses[index];
+ view.Entity.SpiralAbyss = webSpiralAbyss;
+ await spiralAbyssRecordDbService.UpdateSpiralAbyssEntryAsync(view.Entity).ConfigureAwait(false);
+
+ await taskContext.SwitchToMainThreadAsync();
+ spiralAbysses.RemoveAt(index);
+ spiralAbysses.Insert(index, SpiralAbyssView.From(view.Entity, metadataContext));
}
else
{
SpiralAbyssEntry newEntry = SpiralAbyssEntry.From(userAndUid.Uid.Value, webSpiralAbyss);
await taskContext.SwitchToMainThreadAsync();
- spiralAbysses.Insert(0, newEntry);
+ spiralAbysses.Insert(0, SpiralAbyssView.From(newEntry, metadataContext));
await taskContext.SwitchToBackgroundAsync();
await spiralAbyssRecordDbService.AddSpiralAbyssEntryAsync(newEntry).ConfigureAwait(false);
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/AchievementPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/AchievementPage.xaml
index 090b434e..185fe6fd 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/AchievementPage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/AchievementPage.xaml
@@ -188,12 +188,17 @@
-
+
+
+
+
+
+
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/SpiralAbyssRecordPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/SpiralAbyssRecordPage.xaml
index 96a88c80..a19e01e1 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/SpiralAbyssRecordPage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/SpiralAbyssRecordPage.xaml
@@ -27,15 +27,15 @@
IsPaneOpen="True"
OpenPaneLength="120"
PaneBackground="Transparent"
- Visibility="{Binding SpiralAbyssView, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
+ Visibility="{Binding SelectedView, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
+ SelectedItem="{Binding SelectedView, Mode=TwoWay}">
-
+
@@ -55,30 +55,32 @@
Label="{shcm:ResourceString Name=ViewSpiralAbyssRefresh}"/>
-
+
+
+ 0
+ 0
+ 0
+
-
+
+
-
- 0
- 0
- 0
-
-
-
+
+
-
+
+
@@ -88,13 +90,19 @@
-
+
-
+
+
+
-
-
+
-
+
IdScheduleMap { get; set; } = default!;
+
+ public Dictionary IdFloorMap { get; set; } = default!;
+
+ public Dictionary> IdLevelGroupMap { get; set; } = default!;
+
+ public Dictionary IdMonsterMap { get; set; } = default!;
+
+ public Dictionary IdAvatarMap { get; set; } = default!;
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssRecordViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssRecordViewModel.cs
index a81297e3..d3d08bf7 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssRecordViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssRecordViewModel.cs
@@ -27,42 +27,22 @@ internal sealed partial class SpiralAbyssRecordViewModel : Abstraction.ViewModel
{
private readonly ISpiralAbyssRecordService spiralAbyssRecordService;
private readonly HomaSpiralAbyssClient spiralAbyssClient;
- private readonly IMetadataService metadataService;
private readonly IInfoBarService infoBarService;
private readonly ITaskContext taskContext;
private readonly IUserService userService;
- private Dictionary? idAvatarMap;
- private ObservableCollection? spiralAbyssEntries;
- private SpiralAbyssEntry? selectedEntry;
- private SpiralAbyssView? spiralAbyssView;
+ private ObservableCollection? spiralAbyssEntries;
+ private SpiralAbyssView? selectedView;
///
/// 深渊记录
///
- public ObservableCollection? SpiralAbyssEntries { get => spiralAbyssEntries; set => SetProperty(ref spiralAbyssEntries, value); }
+ public ObservableCollection? SpiralAbyssEntries { get => spiralAbyssEntries; set => SetProperty(ref spiralAbyssEntries, value); }
///
/// 选中的深渊信息
///
- public SpiralAbyssEntry? SelectedEntry
- {
- get => selectedEntry; set
- {
- // We dont need to check the result here,
- // just refresh the view anyway.
- SetProperty(ref selectedEntry, value);
- if (value is not null && idAvatarMap is not null)
- {
- SpiralAbyssView = new(value.SpiralAbyss, idAvatarMap);
- }
- }
- }
-
- ///
- /// 深渊的只读视图
- ///
- public SpiralAbyssView? SpiralAbyssView { get => spiralAbyssView; set => SetProperty(ref spiralAbyssView, value); }
+ public SpiralAbyssView? SelectedView { get => selectedView; set => SetProperty(ref selectedView, value); }
///
public void Receive(UserChangedMessage message)
@@ -73,17 +53,14 @@ internal sealed partial class SpiralAbyssRecordViewModel : Abstraction.ViewModel
}
else
{
- SpiralAbyssView = null;
+ SelectedView = null;
}
}
protected override async ValueTask InitializeUIAsync()
{
- if (await metadataService.InitializeAsync().ConfigureAwait(false))
+ if (await spiralAbyssRecordService.InitializeAsync().ConfigureAwait(false))
{
- idAvatarMap = await metadataService.GetIdToAvatarMapAsync().ConfigureAwait(false);
- idAvatarMap = AvatarIds.WithPlayers(idAvatarMap);
-
if (UserAndUid.TryFromUser(userService.Current, out UserAndUid? userAndUid))
{
await UpdateSpiralAbyssCollectionAsync(userAndUid).ConfigureAwait(false);
@@ -100,13 +77,13 @@ internal sealed partial class SpiralAbyssRecordViewModel : Abstraction.ViewModel
private async ValueTask UpdateSpiralAbyssCollectionAsync(UserAndUid userAndUid)
{
- ObservableCollection? temp = null;
+ ObservableCollection? collection = null;
try
{
using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
{
- temp = await spiralAbyssRecordService
- .GetSpiralAbyssCollectionAsync(userAndUid)
+ collection = await spiralAbyssRecordService
+ .GetSpiralAbyssViewCollectionAsync(userAndUid)
.ConfigureAwait(false);
}
}
@@ -115,8 +92,8 @@ internal sealed partial class SpiralAbyssRecordViewModel : Abstraction.ViewModel
}
await taskContext.SwitchToMainThreadAsync();
- SpiralAbyssEntries = temp;
- SelectedEntry = SpiralAbyssEntries?.FirstOrDefault();
+ SpiralAbyssEntries = collection;
+ SelectedView = SpiralAbyssEntries?.FirstOrDefault();
}
[Command("RefreshCommand")]
@@ -140,7 +117,7 @@ internal sealed partial class SpiralAbyssRecordViewModel : Abstraction.ViewModel
}
await taskContext.SwitchToMainThreadAsync();
- SelectedEntry = SpiralAbyssEntries.FirstOrDefault();
+ SelectedView = SpiralAbyssEntries.FirstOrDefault();
}
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssView.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssView.cs
index adf28d8f..d6710711 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssView.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyss/SpiralAbyssView.cs
@@ -1,6 +1,11 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using Snap.Hutao.Core.Abstraction;
+using Snap.Hutao.Model;
+using Snap.Hutao.Model.Entity;
+using Snap.Hutao.Model.Metadata.Avatar;
+using Snap.Hutao.Model.Metadata.Tower;
using Snap.Hutao.Model.Primitive;
namespace Snap.Hutao.ViewModel.SpiralAbyss;
@@ -9,27 +14,47 @@ namespace Snap.Hutao.ViewModel.SpiralAbyss;
/// 深渊视图
///
[HighQuality]
-internal sealed class SpiralAbyssView
+internal sealed class SpiralAbyssView : IEntityOnly,
+ IMappingFrom
{
+ private readonly SpiralAbyssEntry entity;
+
///
/// 构造一个新的深渊视图
///
- /// 深渊信息
+ /// 实体
/// Id角色映射
- public SpiralAbyssView(Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss spiralAbyss, Dictionary idAvatarMap)
+ private SpiralAbyssView(SpiralAbyssEntry entity, SpiralAbyssMetadataContext context)
{
+ this.entity = entity;
+ Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss spiralAbyss = entity.SpiralAbyss;
+
+ TowerSchedule towerSchedule = context.IdScheduleMap[(uint)entity.ScheduleId];
+ TimeFormatted = $"{towerSchedule.Open:yyyy/MM/dd HH:mm:ss} - {towerSchedule.Close:yyyy/MM/dd HH:mm:ss}";
+
+ BlessingName = towerSchedule.BuffName;
+ Blessings = towerSchedule.Descriptions;
+
TotalBattleTimes = spiralAbyss.TotalBattleTimes;
TotalStar = spiralAbyss.TotalStar;
MaxFloor = spiralAbyss.MaxFloor;
- Reveals = spiralAbyss.RevealRank.SelectList(r => new RankAvatar(r.Value, idAvatarMap[r.AvatarId]));
- Defeat = spiralAbyss.DefeatRank.Select(r => new RankAvatar(r.Value, idAvatarMap[r.AvatarId])).SingleOrDefault();
- Damage = spiralAbyss.DamageRank.Select(r => new RankAvatar(r.Value, idAvatarMap[r.AvatarId])).SingleOrDefault();
- TakeDamage = spiralAbyss.TakeDamageRank.Select(r => new RankAvatar(r.Value, idAvatarMap[r.AvatarId])).SingleOrDefault();
- NormalSkill = spiralAbyss.NormalSkillRank.Select(r => new RankAvatar(r.Value, idAvatarMap[r.AvatarId])).SingleOrDefault();
- EnergySkill = spiralAbyss.EnergySkillRank.Select(r => new RankAvatar(r.Value, idAvatarMap[r.AvatarId])).SingleOrDefault();
- Floors = spiralAbyss.Floors.Select(f => new FloorView(f, idAvatarMap)).Reverse().ToList();
+ Reveals = spiralAbyss.RevealRank.SelectList(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId]));
+ Defeat = spiralAbyss.DefeatRank.Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
+ Damage = spiralAbyss.DamageRank.Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
+ TakeDamage = spiralAbyss.TakeDamageRank.Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
+ NormalSkill = spiralAbyss.NormalSkillRank.Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
+ EnergySkill = spiralAbyss.EnergySkillRank.Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
+ Floors = spiralAbyss.Floors.Select(f => new FloorView(f, context.IdAvatarMap)).Reverse().ToList();
}
+ public SpiralAbyssEntry Entity { get => entity; }
+
+ public string TimeFormatted { get; }
+
+ public string BlessingName { get; }
+
+ public List Blessings { get; }
+
///
/// 战斗次数
///
@@ -79,4 +104,9 @@ internal sealed class SpiralAbyssView
/// 层信息
///
public List Floors { get; }
+
+ public static SpiralAbyssView From(SpiralAbyssEntry entity, SpiralAbyssMetadataContext context)
+ {
+ return new(entity, context);
+ }
}
\ No newline at end of file