add refresh time for avatar property

This commit is contained in:
DismissedLight
2023-08-27 17:02:23 +08:00
parent 00f083608e
commit 8ca6251d33
14 changed files with 169 additions and 42 deletions

View File

@@ -48,7 +48,7 @@
<GridLength x:Key="CompatGridLength2">288</GridLength> <GridLength x:Key="CompatGridLength2">288</GridLength>
<x:Double x:Key="CompatSplitViewOpenPaneLength">212</x:Double> <x:Double x:Key="CompatSplitViewOpenPaneLength">212</x:Double>
<x:Double x:Key="CompatSplitViewOpenPaneLength2">304</x:Double> <x:Double x:Key="CompatSplitViewOpenPaneLength2">304</x:Double>
<x:Double x:Key="CompatSplitViewOpenPaneLength3">320</x:Double>
<x:Double x:Key="HomeAdaptiveCardHeight">180</x:Double> <x:Double x:Key="HomeAdaptiveCardHeight">180</x:Double>
<x:Double x:Key="ContentDialogMinHeight">64</x:Double> <x:Double x:Key="ContentDialogMinHeight">64</x:Double>
<x:Double x:Key="LargeAppBarButtonWidth">100</x:Double> <x:Double x:Key="LargeAppBarButtonWidth">100</x:Double>

View File

@@ -9,6 +9,8 @@ namespace Snap.Hutao.Extension;
[HighQuality] [HighQuality]
internal static class DateTimeOffsetExtension internal static class DateTimeOffsetExtension
{ {
public static readonly DateTimeOffset DatebaseDefaultTime = new(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0));
/// <summary> /// <summary>
/// 从Unix时间戳转换 /// 从Unix时间戳转换
/// </summary> /// </summary>

View File

@@ -58,7 +58,15 @@ internal sealed class DailyNoteEntry : ObservableObject, IMappingFrom<DailyNoteE
public DateTimeOffset RefreshTime { get; set; } public DateTimeOffset RefreshTime { get; set; }
[NotMapped] [NotMapped]
public string RefreshTimeFormatted { get => SH.ModelEntityDailyNoteRefreshTimeFormat.Format(RefreshTime); } public string RefreshTimeFormatted
{
get
{
return RefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime
? SH.ModelEntityDailyNoteNotRefreshed
: SH.ModelEntityDailyNoteRefreshTimeFormat.Format(RefreshTime);
}
}
/// <summary> /// <summary>
/// 树脂提醒阈值 /// 树脂提醒阈值

View File

@@ -420,6 +420,15 @@ namespace Snap.Hutao.Resource.Localization {
} }
} }
/// <summary>
/// 查找类似 尚未刷新 的本地化字符串。
/// </summary>
internal static string ModelEntityDailyNoteNotRefreshed {
get {
return ResourceManager.GetString("ModelEntityDailyNoteNotRefreshed", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 刷新于 {0:yyyy/MM/dd HH:mm:ss} 的本地化字符串。 /// 查找类似 刷新于 {0:yyyy/MM/dd HH:mm:ss} 的本地化字符串。
/// </summary> /// </summary>
@@ -1122,6 +1131,60 @@ namespace Snap.Hutao.Resource.Localization {
} }
} }
/// <summary>
/// 查找类似 养成计算:尚未刷新 的本地化字符串。
/// </summary>
internal static string ServiceAvatarInfoSummaryCalculatorNotRefreshed {
get {
return ResourceManager.GetString("ServiceAvatarInfoSummaryCalculatorNotRefreshed", resourceCulture);
}
}
/// <summary>
/// 查找类似 养成计算:{0:MM-dd HH:mm} 的本地化字符串。
/// </summary>
internal static string ServiceAvatarInfoSummaryCalculatorRefreshTimeFormat {
get {
return ResourceManager.GetString("ServiceAvatarInfoSummaryCalculatorRefreshTimeFormat", resourceCulture);
}
}
/// <summary>
/// 查找类似 我的角色:尚未刷新 的本地化字符串。
/// </summary>
internal static string ServiceAvatarInfoSummaryGameRecordNotRefreshed {
get {
return ResourceManager.GetString("ServiceAvatarInfoSummaryGameRecordNotRefreshed", resourceCulture);
}
}
/// <summary>
/// 查找类似 我的角色:{0:MM-dd HH:mm} 的本地化字符串。
/// </summary>
internal static string ServiceAvatarInfoSummaryGameRecordRefreshTimeFormat {
get {
return ResourceManager.GetString("ServiceAvatarInfoSummaryGameRecordRefreshTimeFormat", resourceCulture);
}
}
/// <summary>
/// 查找类似 角色橱窗:尚未刷新 的本地化字符串。
/// </summary>
internal static string ServiceAvatarInfoSummaryShowcaseNotRefreshed {
get {
return ResourceManager.GetString("ServiceAvatarInfoSummaryShowcaseNotRefreshed", resourceCulture);
}
}
/// <summary>
/// 查找类似 角色橱窗:{0:MM-dd HH:mm} 的本地化字符串。
/// </summary>
internal static string ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat {
get {
return ResourceManager.GetString("ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 保存养成计划状态失败 的本地化字符串。 /// 查找类似 保存养成计划状态失败 的本地化字符串。
/// </summary> /// </summary>

View File

@@ -237,6 +237,9 @@
<data name="ModelBindingUserInitializationFailed" xml:space="preserve"> <data name="ModelBindingUserInitializationFailed" xml:space="preserve">
<value>网络异常</value> <value>网络异常</value>
</data> </data>
<data name="ModelEntityDailyNoteNotRefreshed" xml:space="preserve">
<value>尚未刷新</value>
</data>
<data name="ModelEntityDailyNoteRefreshTimeFormat" xml:space="preserve"> <data name="ModelEntityDailyNoteRefreshTimeFormat" xml:space="preserve">
<value>刷新于 {0:yyyy/MM/dd HH:mm:ss}</value> <value>刷新于 {0:yyyy/MM/dd HH:mm:ss}</value>
</data> </data>
@@ -527,6 +530,24 @@
<value>风元素抗性</value> <value>风元素抗性</value>
<comment>Need EXACT same string in game</comment> <comment>Need EXACT same string in game</comment>
</data> </data>
<data name="ServiceAvatarInfoSummaryCalculatorNotRefreshed" xml:space="preserve">
<value>养成计算:尚未刷新</value>
</data>
<data name="ServiceAvatarInfoSummaryCalculatorRefreshTimeFormat" xml:space="preserve">
<value>养成计算:{0:MM-dd HH:mm}</value>
</data>
<data name="ServiceAvatarInfoSummaryGameRecordNotRefreshed" xml:space="preserve">
<value>我的角色:尚未刷新</value>
</data>
<data name="ServiceAvatarInfoSummaryGameRecordRefreshTimeFormat" xml:space="preserve">
<value>我的角色:{0:MM-dd HH:mm}</value>
</data>
<data name="ServiceAvatarInfoSummaryShowcaseNotRefreshed" xml:space="preserve">
<value>角色橱窗:尚未刷新</value>
</data>
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>角色橱窗:{0:MM-dd HH:mm}</value>
</data>
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve"> <data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>保存养成计划状态失败</value> <value>保存养成计划状态失败</value>
</data> </data>

View File

@@ -40,7 +40,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
/// <param name="webInfos">Enka信息</param> /// <param name="webInfos">Enka信息</param>
/// <param name="token">取消令牌</param> /// <param name="token">取消令牌</param>
/// <returns>角色列表</returns> /// <returns>角色列表</returns>
public List<EnkaAvatarInfo> UpdateDbAvatarInfosByShowcase(string uid, IEnumerable<EnkaAvatarInfo> webInfos, CancellationToken token) public List<EntityAvatarInfo> UpdateDbAvatarInfosByShowcase(string uid, IEnumerable<EnkaAvatarInfo> webInfos, CancellationToken token)
{ {
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
List<EntityAvatarInfo> dbInfos = avatarInfoDbService.GetAvatarInfoListByUid(uid); List<EntityAvatarInfo> dbInfos = avatarInfoDbService.GetAvatarInfoListByUid(uid);
@@ -63,7 +63,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
} }
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
return avatarInfoDbService.GetAvatarInfoInfoListByUid(uid); return avatarInfoDbService.GetAvatarInfoListByUid(uid);
} }
} }
@@ -73,7 +73,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
/// <param name="userAndUid">用户与角色</param> /// <param name="userAndUid">用户与角色</param>
/// <param name="token">取消令牌</param> /// <param name="token">取消令牌</param>
/// <returns>角色列表</returns> /// <returns>角色列表</returns>
public async ValueTask<List<EnkaAvatarInfo>> UpdateDbAvatarInfosByGameRecordCharacterAsync(UserAndUid userAndUid, CancellationToken token) public async ValueTask<List<EntityAvatarInfo>> UpdateDbAvatarInfosByGameRecordCharacterAsync(UserAndUid userAndUid, CancellationToken token)
{ {
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
string uid = userAndUid.Uid.Value; string uid = userAndUid.Uid.Value;
@@ -121,7 +121,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
} }
} }
return avatarInfoDbService.GetAvatarInfoInfoListByUid(uid); return avatarInfoDbService.GetAvatarInfoListByUid(uid);
} }
/// <summary> /// <summary>
@@ -130,7 +130,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
/// <param name="userAndUid">用户与角色</param> /// <param name="userAndUid">用户与角色</param>
/// <param name="token">取消令牌</param> /// <param name="token">取消令牌</param>
/// <returns>角色列表</returns> /// <returns>角色列表</returns>
public async ValueTask<List<EnkaAvatarInfo>> UpdateDbAvatarInfosByCalculateAvatarDetailAsync(UserAndUid userAndUid, CancellationToken token) public async ValueTask<List<EntityAvatarInfo>> UpdateDbAvatarInfosByCalculateAvatarDetailAsync(UserAndUid userAndUid, CancellationToken token)
{ {
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
string uid = userAndUid.Uid.Value; string uid = userAndUid.Uid.Value;
@@ -173,7 +173,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
} }
} }
return avatarInfoDbService.GetAvatarInfoInfoListByUid(uid); return avatarInfoDbService.GetAvatarInfoListByUid(uid);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore;
using Snap.Hutao.Core.Database; using Snap.Hutao.Core.Database;
using Snap.Hutao.Model.Entity.Database; using Snap.Hutao.Model.Entity.Database;
using EnkaAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo; using EnkaAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
using ModelAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo; using EntityAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
namespace Snap.Hutao.Service.AvatarInfo; namespace Snap.Hutao.Service.AvatarInfo;
@@ -15,7 +15,7 @@ internal sealed partial class AvatarInfoDbService : IAvatarInfoDbService
{ {
private readonly IServiceProvider serviceProvider; private readonly IServiceProvider serviceProvider;
public List<ModelAvatarInfo> GetAvatarInfoListByUid(string uid) public List<EntityAvatarInfo> GetAvatarInfoListByUid(string uid)
{ {
using (IServiceScope scope = serviceProvider.CreateScope()) using (IServiceScope scope = serviceProvider.CreateScope())
{ {
@@ -24,19 +24,6 @@ internal sealed partial class AvatarInfoDbService : IAvatarInfoDbService
} }
} }
public List<EnkaAvatarInfo> GetAvatarInfoInfoListByUid(string uid)
{
using (IServiceScope scope = serviceProvider.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
return appDbContext.AvatarInfos
.AsNoTracking()
.Where(i => i.Uid == uid)
.Select(i => i.Info)
.ToList();
}
}
public void DeleteAvatarInfoRangeByUid(string uid) public void DeleteAvatarInfoRangeByUid(string uid)
{ {
using (IServiceScope scope = serviceProvider.CreateScope()) using (IServiceScope scope = serviceProvider.CreateScope())

View File

@@ -10,6 +10,7 @@ using Snap.Hutao.Web.Enka;
using Snap.Hutao.Web.Enka.Model; using Snap.Hutao.Web.Enka.Model;
using Snap.Hutao.Web.Hoyolab; using Snap.Hutao.Web.Hoyolab;
using EnkaAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo; using EnkaAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
using EntityAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
namespace Snap.Hutao.Service.AvatarInfo; namespace Snap.Hutao.Service.AvatarInfo;
@@ -56,28 +57,28 @@ internal sealed partial class AvatarInfoService : IAvatarInfoService
return new(RefreshResult.ShowcaseNotOpen, default); return new(RefreshResult.ShowcaseNotOpen, default);
} }
List<EnkaAvatarInfo> list = avatarInfoDbBulkOperation.UpdateDbAvatarInfosByShowcase(userAndUid.Uid.Value, resp.AvatarInfoList, token); List<EntityAvatarInfo> list = avatarInfoDbBulkOperation.UpdateDbAvatarInfosByShowcase(userAndUid.Uid.Value, resp.AvatarInfoList, token);
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false); Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
return new(RefreshResult.Ok, summary); return new(RefreshResult.Ok, summary);
} }
case RefreshOption.RequestFromHoyolabGameRecord: case RefreshOption.RequestFromHoyolabGameRecord:
{ {
List<EnkaAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByGameRecordCharacterAsync(userAndUid, token).ConfigureAwait(false); List<EntityAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByGameRecordCharacterAsync(userAndUid, token).ConfigureAwait(false);
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false); Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
return new(RefreshResult.Ok, summary); return new(RefreshResult.Ok, summary);
} }
case RefreshOption.RequestFromHoyolabCalculate: case RefreshOption.RequestFromHoyolabCalculate:
{ {
List<EnkaAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByCalculateAvatarDetailAsync(userAndUid, token).ConfigureAwait(false); List<EntityAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByCalculateAvatarDetailAsync(userAndUid, token).ConfigureAwait(false);
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false); Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
return new(RefreshResult.Ok, summary); return new(RefreshResult.Ok, summary);
} }
default: default:
{ {
List<EnkaAvatarInfo> list = avatarInfoDbService.GetAvatarInfoInfoListByUid(userAndUid.Uid.Value); List<EntityAvatarInfo> list = avatarInfoDbService.GetAvatarInfoListByUid(userAndUid.Uid.Value);
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false); Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
token.ThrowIfCancellationRequested(); token.ThrowIfCancellationRequested();
return new(RefreshResult.Ok, summary.Avatars.Count == 0 ? null : summary); return new(RefreshResult.Ok, summary.Avatars.Count == 0 ? null : summary);
@@ -96,7 +97,7 @@ internal sealed partial class AvatarInfoService : IAvatarInfoService
?? await enkaClient.GetDataAsync(uid, token).ConfigureAwait(false); ?? await enkaClient.GetDataAsync(uid, token).ConfigureAwait(false);
} }
private async ValueTask<Summary> GetSummaryCoreAsync(IEnumerable<EnkaAvatarInfo> avatarInfos, CancellationToken token) private async ValueTask<Summary> GetSummaryCoreAsync(IEnumerable<Model.Entity.AvatarInfo> avatarInfos, CancellationToken token)
{ {
using (ValueStopwatch.MeasureExecution(logger)) using (ValueStopwatch.MeasureExecution(logger))
{ {

View File

@@ -17,5 +17,5 @@ internal interface ISummaryFactory
/// <param name="avatarInfos">角色列表</param> /// <param name="avatarInfos">角色列表</param>
/// <param name="token">取消令牌</param> /// <param name="token">取消令牌</param>
/// <returns>简述对象</returns> /// <returns>简述对象</returns>
ValueTask<Summary> CreateAsync(IEnumerable<Web.Enka.Model.AvatarInfo> avatarInfos, CancellationToken token); ValueTask<Summary> CreateAsync(IEnumerable<Model.Entity.AvatarInfo> avatarInfos, CancellationToken token);
} }

View File

@@ -6,6 +6,7 @@ using Snap.Hutao.Model.Metadata.Converter;
using Snap.Hutao.Model.Primitive; using Snap.Hutao.Model.Primitive;
using Snap.Hutao.ViewModel.AvatarProperty; using Snap.Hutao.ViewModel.AvatarProperty;
using Snap.Hutao.Web.Enka.Model; using Snap.Hutao.Web.Enka.Model;
using EntityAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
using MetadataAvatar = Snap.Hutao.Model.Metadata.Avatar.Avatar; using MetadataAvatar = Snap.Hutao.Model.Metadata.Avatar.Avatar;
using MetadataWeapon = Snap.Hutao.Model.Metadata.Weapon.Weapon; using MetadataWeapon = Snap.Hutao.Model.Metadata.Weapon.Weapon;
using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo; using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
@@ -21,7 +22,12 @@ namespace Snap.Hutao.Service.AvatarInfo.Factory;
[HighQuality] [HighQuality]
internal sealed class SummaryAvatarFactory internal sealed class SummaryAvatarFactory
{ {
private static readonly DateTimeOffset DefaultRefreshTime = new(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0));
private readonly ModelAvatarInfo avatarInfo; private readonly ModelAvatarInfo avatarInfo;
private readonly DateTimeOffset showcaseRefreshTime;
private readonly DateTimeOffset gameRecordRefreshTime;
private readonly DateTimeOffset calculatorRefreshTime;
private readonly SummaryMetadataContext metadataContext; private readonly SummaryMetadataContext metadataContext;
/// <summary> /// <summary>
@@ -29,10 +35,14 @@ internal sealed class SummaryAvatarFactory
/// </summary> /// </summary>
/// <param name="metadataContext">元数据上下文</param> /// <param name="metadataContext">元数据上下文</param>
/// <param name="avatarInfo">角色信息</param> /// <param name="avatarInfo">角色信息</param>
public SummaryAvatarFactory(SummaryMetadataContext metadataContext, ModelAvatarInfo avatarInfo) public SummaryAvatarFactory(SummaryMetadataContext metadataContext, EntityAvatarInfo avatarInfo)
{ {
this.metadataContext = metadataContext; this.metadataContext = metadataContext;
this.avatarInfo = avatarInfo; this.avatarInfo = avatarInfo.Info;
showcaseRefreshTime = avatarInfo.ShowcaseRefreshTime;
gameRecordRefreshTime = avatarInfo.GameRecordRefreshTime;
calculatorRefreshTime = avatarInfo.CalculatorRefreshTime;
} }
/// <summary> /// <summary>
@@ -67,6 +77,17 @@ internal sealed class SummaryAvatarFactory
Weapon = reliquaryAndWeapon.Weapon, Weapon = reliquaryAndWeapon.Weapon,
Reliquaries = reliquaryAndWeapon.Reliquaries, Reliquaries = reliquaryAndWeapon.Reliquaries,
Score = $"{reliquaryAndWeapon.Reliquaries.Sum(r => r.Score):F2}", Score = $"{reliquaryAndWeapon.Reliquaries.Sum(r => r.Score):F2}",
// times
ShowcaseRefreshTimeFormat = showcaseRefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime
? SH.ServiceAvatarInfoSummaryShowcaseNotRefreshed
: SH.ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat.Format(showcaseRefreshTime),
GameRecordRefreshTimeFormat = gameRecordRefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime
? SH.ServiceAvatarInfoSummaryGameRecordNotRefreshed
: SH.ServiceAvatarInfoSummaryGameRecordRefreshTimeFormat.Format(gameRecordRefreshTime),
CalculatorRefreshTimeFormat = calculatorRefreshTime == DateTimeOffsetExtension.DatebaseDefaultTime
? SH.ServiceAvatarInfoSummaryCalculatorNotRefreshed
: SH.ServiceAvatarInfoSummaryCalculatorRefreshTimeFormat.Format(calculatorRefreshTime),
}; };
ApplyCostumeIconOrDefault(ref propertyAvatar, avatar); ApplyCostumeIconOrDefault(ref propertyAvatar, avatar);

View File

@@ -4,7 +4,6 @@
using Snap.Hutao.Model.Metadata; using Snap.Hutao.Model.Metadata;
using Snap.Hutao.Service.Metadata; using Snap.Hutao.Service.Metadata;
using Snap.Hutao.ViewModel.AvatarProperty; using Snap.Hutao.ViewModel.AvatarProperty;
using ModelAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo;
namespace Snap.Hutao.Service.AvatarInfo.Factory; namespace Snap.Hutao.Service.AvatarInfo.Factory;
@@ -19,7 +18,7 @@ internal sealed partial class SummaryFactory : ISummaryFactory
private readonly IMetadataService metadataService; private readonly IMetadataService metadataService;
/// <inheritdoc/> /// <inheritdoc/>
public async ValueTask<Summary> CreateAsync(IEnumerable<ModelAvatarInfo> avatarInfos, CancellationToken token) public async ValueTask<Summary> CreateAsync(IEnumerable<Model.Entity.AvatarInfo> avatarInfos, CancellationToken token)
{ {
SummaryMetadataContext metadataContext = new() SummaryMetadataContext metadataContext = new()
{ {
@@ -35,7 +34,7 @@ internal sealed partial class SummaryFactory : ISummaryFactory
return new() return new()
{ {
Avatars = avatarInfos Avatars = avatarInfos
.Where(a => !AvatarIds.IsPlayer(a.AvatarId)) .Where(a => !AvatarIds.IsPlayer(a.Info.AvatarId))
.Select(a => new SummaryAvatarFactory(metadataContext, a).Create()) .Select(a => new SummaryAvatarFactory(metadataContext, a).Create())
.OrderByDescending(a => a.LevelNumber) .OrderByDescending(a => a.LevelNumber)
.ThenBy(a => a.Name) .ThenBy(a => a.Name)

View File

@@ -1,8 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved. // Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license. // Licensed under the MIT license.
using EnkaAvatarInfo = Snap.Hutao.Web.Enka.Model.AvatarInfo; using EntityAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
using ModelAvatarInfo = Snap.Hutao.Model.Entity.AvatarInfo;
namespace Snap.Hutao.Service.AvatarInfo; namespace Snap.Hutao.Service.AvatarInfo;
@@ -10,7 +9,5 @@ internal interface IAvatarInfoDbService
{ {
void DeleteAvatarInfoRangeByUid(string uid); void DeleteAvatarInfoRangeByUid(string uid);
List<EnkaAvatarInfo> GetAvatarInfoInfoListByUid(string uid); List<EntityAvatarInfo> GetAvatarInfoListByUid(string uid);
List<ModelAvatarInfo> GetAvatarInfoListByUid(string uid);
} }

View File

@@ -227,7 +227,7 @@
Grid.Row="1" Grid.Row="1"
DisplayMode="Inline" DisplayMode="Inline"
IsPaneOpen="True" IsPaneOpen="True"
OpenPaneLength="{StaticResource CompatSplitViewOpenPaneLength}" OpenPaneLength="{StaticResource CompatSplitViewOpenPaneLength3}"
PaneBackground="Transparent"> PaneBackground="Transparent">
<SplitView.Pane> <SplitView.Pane>
<ListView ItemsSource="{Binding Summary.Avatars}" SelectedItem="{Binding SelectedAvatar, Mode=TwoWay}"> <ListView ItemsSource="{Binding Summary.Avatars}" SelectedItem="{Binding SelectedAvatar, Mode=TwoWay}">
@@ -236,7 +236,8 @@
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/> <ColumnDefinition Width="auto"/>
<ColumnDefinition/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<shci:CachedImage <shci:CachedImage
Grid.Column="0" Grid.Column="0"
@@ -245,13 +246,34 @@
Margin="0,0,12,12" Margin="0,0,12,12"
Source="{Binding SideIcon, Mode=OneWay}"/> Source="{Binding SideIcon, Mode=OneWay}"/>
<StackPanel Grid.Column="1" VerticalAlignment="Center"> <StackPanel Grid.Column="1" VerticalAlignment="Center">
<TextBlock Margin="12,0,0,0" Text="{Binding Name}"/> <TextBlock
Margin="12,0,0,0"
Text="{Binding Name}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"/>
<TextBlock <TextBlock
Margin="12,0,0,0" Margin="12,0,0,0"
Opacity="0.7" Opacity="0.7"
Style="{StaticResource CaptionTextBlockStyle}" Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding Level}"/> Text="{Binding Level}"/>
</StackPanel> </StackPanel>
<StackPanel
Grid.Column="2"
VerticalAlignment="Center"
Opacity="0.7">
<TextBlock
FontSize="11"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding ShowcaseRefreshTimeFormat}"/>
<TextBlock
FontSize="11"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding GameRecordRefreshTimeFormat}"/>
<TextBlock
FontSize="11"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding CalculatorRefreshTimeFormat}"/>
</StackPanel>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
</ListView.ItemTemplate> </ListView.ItemTemplate>

View File

@@ -93,6 +93,12 @@ internal sealed class AvatarView : INameIconSide, ICalculableSource<ICalculableA
/// </summary> /// </summary>
public uint FetterLevel { get; set; } public uint FetterLevel { get; set; }
public string ShowcaseRefreshTimeFormat { get; set; }
public string GameRecordRefreshTimeFormat { get; set; }
public string CalculatorRefreshTimeFormat { get; set; }
/// <summary> /// <summary>
/// Id /// Id
/// </summary> /// </summary>