add avatar page

This commit is contained in:
DismissedLight
2022-07-10 16:38:02 +08:00
parent 344e5cd31b
commit 3d87246c9e
34 changed files with 583 additions and 83 deletions

View File

@@ -2,8 +2,7 @@
x:Class="Snap.Hutao.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:system="using:System">
xmlns:muxc="using:Microsoft.UI.Xaml.Controls">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
@@ -19,14 +18,16 @@
<StaticResource x:Key="ApplicationPageBackgroundThemeBrush" ResourceKey="ControlFillColorTransparentBrush" />
<FontFamily x:Key="SymbolThemeFontFamily">ms-appx:///Resource/Font/Segoe Fluent Icons.ttf#Segoe Fluent Icons</FontFamily>
<Thickness x:Key="InfoBarIconMargin">6,16,16,16</Thickness>
<Thickness x:Key="InfoBarContentRootPadding">16,0,0,0</Thickness>
<CornerRadius x:Key="CompatCornerRadius">4</CornerRadius>
<CornerRadius x:Key="CompatCornerRadiusTop">4,4,0,0</CornerRadius>
<CornerRadius x:Key="CompatCornerRadiusRight">0,4,4,0</CornerRadius>
<CornerRadius x:Key="CompatCornerRadiusBottom">0,0,4,4</CornerRadius>
<CornerRadius x:Key="SmallCompatCornerRadius">2,2,2,2</CornerRadius>
<CornerRadius x:Key="CompatCornerRadius">6</CornerRadius>
<CornerRadius x:Key="CompatCornerRadiusTop">6,6,0,0</CornerRadius>
<CornerRadius x:Key="CompatCornerRadiusRight">0,6,6,0</CornerRadius>
<CornerRadius x:Key="CompatCornerRadiusBottom">0,0,6,6</CornerRadius>
<CornerRadius x:Key="SmallCompatCornerRadius">4</CornerRadius>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -6,7 +6,9 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
using Microsoft.Windows.AppLifecycle;
using Snap.Hutao.Core.Logging;
using Snap.Hutao.Extension;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.Metadata;
using System.Diagnostics;
using Windows.ApplicationModel.Activation;
@@ -66,6 +68,11 @@ public partial class App : Application
Window = Ioc.Default.GetRequiredService<MainWindow>();
Window.Activate();
if (Ioc.Default.GetRequiredService<IMetadataService>() is IMetadataInitializer initializer)
{
initializer.InitializeInternalAsync().SafeForget();
}
if (uri != null)
{
Ioc.Default.GetRequiredService<IInfoBarService>().Information(uri.ToString());

View File

@@ -0,0 +1,24 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Snap.Hutao.Core;
namespace Snap.Hutao.Control;
/// <summary>
/// 绑定探针
/// </summary>
public class BindingProxy : DependencyObject
{
private static readonly DependencyProperty DataProperty = Property<BindingProxy>.Depend<object>(nameof(DataContext));
/// <summary>
/// 数据上下文
/// </summary>
public object? DataContext
{
get => GetValue(DataProperty);
set => SetValue(DataProperty, value);
}
}

View File

@@ -16,7 +16,7 @@ public class CachedImage : ImageEx
{
static CachedImage()
{
ImageCache.Instance.CacheDuration = Timeout.InfiniteTimeSpan;
ImageCache.Instance.CacheDuration = TimeSpan.FromDays(30);
ImageCache.Instance.RetryCount = 3;
}

View File

@@ -32,4 +32,9 @@ internal static class SettingKeys
/// 窗体底部
/// </summary>
public const string WindowBottom = "WindowBottom";
/// <summary>
/// 导航侧栏是否展开
/// </summary>
public const string IsNavPaneOpen = "IsNavPaneOpen";
}

View File

@@ -14,8 +14,8 @@ public struct POINT
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
X = x;
Y = y;
}
public static implicit operator System.Drawing.Point(POINT p)

View File

@@ -15,9 +15,11 @@
</Grid.RowDefinitions>
<view:TitleView
Margin="48,0,0,0"
Grid.Row="0"
x:Name="TitleBarView"/>
<view:MainView
Grid.Row="1"/>
Grid.Row="0"
Grid.RowSpan="2"/>
</Grid>
</Window>

View File

@@ -54,20 +54,19 @@ public sealed partial class MainWindow : Window
private void InitializeWindow()
{
RECT rect = RetriveWindowRect();
if (rect.Size.IsEmpty)
if (!rect.Size.IsEmpty)
{
return;
WINDOWPLACEMENT windowPlacement = new()
{
Length = Marshal.SizeOf<WINDOWPLACEMENT>(),
MaxPosition = new Point(-1, -1),
NormalPosition = rect,
ShowCmd = ShowWindowCommand.Normal,
};
User32.SetWindowPlacement(handle, ref windowPlacement);
}
WINDOWPLACEMENT windowPlacement = new()
{
Length = Marshal.SizeOf<WINDOWPLACEMENT>(),
MaxPosition = new Point(-1, -1),
NormalPosition = rect,
ShowCmd = ShowWindowCommand.Normal,
};
User32.SetWindowPlacement(handle, ref windowPlacement);
User32.SetWindowText(handle, "胡桃");
bool micaApplied = new SystemBackdrop(this).TrySetBackdrop();

View File

@@ -1,6 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Metadata.Annotation;
namespace Snap.Hutao.Model.Intrinsic;
/// <summary>
@@ -18,6 +20,7 @@ public enum FightProperty
/// 基础生命值
/// </summary>
[Description("基础生命值")]
[Format(FormatMethod.Integer)]
FIGHT_PROP_BASE_HP = 1,
/// <summary>
@@ -29,12 +32,14 @@ public enum FightProperty
/// 生命值加成百分比
/// </summary>
[Description("生命值")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_HP_PERCENT = 3,
/// <summary>
/// 基础攻击力
/// </summary>
[Description("基础攻击力")]
[Format(FormatMethod.Integer)]
FIGHT_PROP_BASE_ATTACK = 4,
/// <summary>
@@ -46,12 +51,14 @@ public enum FightProperty
/// 攻击力百分比
/// </summary>
[Description("攻击力")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_ATTACK_PERCENT = 6,
/// <summary>
/// 基础防御力
/// </summary>
[Description("基础防御力")]
[Format(FormatMethod.Integer)]
FIGHT_PROP_BASE_DEFENSE = 7,
/// <summary>
@@ -63,6 +70,7 @@ public enum FightProperty
/// 防御力百分比
/// </summary>
[Description("防御力")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_DEFENSE_PERCENT = 9,
/// <summary>
@@ -89,6 +97,7 @@ public enum FightProperty
/// 暴击率
/// </summary>
[Description("暴击率")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_CRITICAL = 20,
/// <summary>
@@ -100,12 +109,14 @@ public enum FightProperty
/// 暴击伤害
/// </summary>
[Description("暴击伤害")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_CRITICAL_HURT = 22,
/// <summary>
/// 元素充能效率
/// </summary>
[Description("元素充能效率")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_CHARGE_EFFICIENCY = 23,
/// <summary>
@@ -122,6 +133,7 @@ public enum FightProperty
/// 治疗提升
/// </summary>
[Description("治疗加成")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_HEAL_ADD = 26,
/// <summary>
@@ -133,6 +145,7 @@ public enum FightProperty
/// 元素精通
/// </summary>
[Description("元素精通")]
[Format(FormatMethod.Integer)]
FIGHT_PROP_ELEMENT_MASTERY = 28,
/// <summary>
@@ -144,6 +157,7 @@ public enum FightProperty
/// 物理伤害加成
/// </summary>
[Description("物理伤害加成")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_PHYSICAL_ADD_HURT = 30,
/// <summary>
@@ -160,18 +174,21 @@ public enum FightProperty
/// 火元素伤害加成
/// </summary>
[Description("火元素伤害加成")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_FIRE_ADD_HURT = 40,
/// <summary>
/// 雷元素伤害加成
/// </summary>
[Description("雷元素伤害加成")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_ELEC_ADD_HURT = 41,
/// <summary>
/// 水元素伤害加成
/// </summary>
[Description("水元素伤害加成")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_WATER_ADD_HURT = 42,
/// <summary>
@@ -183,18 +200,21 @@ public enum FightProperty
/// 风元素伤害加成
/// </summary>
[Description("风元素伤害加成")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_WIND_ADD_HURT = 44,
/// <summary>
/// 岩元素伤害加成
/// </summary>
[Description("岩元素伤害加成")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_ROCK_ADD_HURT = 45,
/// <summary>
/// 冰元素伤害加成
/// </summary>
[Description("冰元素伤害加成")]
[Format(FormatMethod.Percent)]
FIGHT_PROP_ICE_ADD_HURT = 46,
/// <summary>

View File

@@ -0,0 +1,27 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using System.Reflection;
namespace Snap.Hutao.Model.Metadata.Annotation;
/// <summary>
/// 枚举拓展
/// </summary>
internal static class EnumExtensions
{
/// <summary>
/// 获取枚举的描述
/// </summary>
/// <typeparam name="TEnum">枚举的类型</typeparam>
/// <param name="enum">枚举值</param>
/// <returns>描述</returns>
internal static FormatMethod GetFormat<TEnum>(this TEnum @enum)
where TEnum : struct, Enum
{
string enumName = Must.NotNull(Enum.GetName(@enum)!);
FieldInfo? field = @enum.GetType().GetField(enumName);
FormatAttribute? attr = field?.GetCustomAttribute<FormatAttribute>();
return attr?.Method ?? FormatMethod.None;
}
}

View File

@@ -0,0 +1,25 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Model.Metadata.Annotation;
/// <summary>
/// 格式特性
/// </summary>
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
internal class FormatAttribute : Attribute
{
/// <summary>
/// 指示该字段应用的格式化方法
/// </summary>
/// <param name="method">格式化方法</param>
public FormatAttribute(FormatMethod method)
{
Method = method;
}
/// <summary>
/// 格式化方法
/// </summary>
public FormatMethod Method { get; init; }
}

View File

@@ -0,0 +1,22 @@
namespace Snap.Hutao.Model.Metadata.Annotation;
/// <summary>
/// 格式化方法
/// </summary>
internal enum FormatMethod
{
/// <summary>
/// 无格式化
/// </summary>
None,
/// <summary>
/// 取整
/// </summary>
Integer,
/// <summary>
/// 百分比
/// </summary>
Percent,
}

View File

@@ -0,0 +1,26 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Data;
using Snap.Hutao.Extension;
using Snap.Hutao.Model.Intrinsic;
namespace Snap.Hutao.Model.Metadata.Converter;
/// <summary>
/// 战斗属性转换器
/// </summary>
internal class FightPropertyConverter : IValueConverter
{
/// <inheritdoc/>
public object Convert(object value, Type targetType, object parameter, string language)
{
return ((FightProperty)value).GetDescription();
}
/// <inheritdoc/>
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw Must.NeverHappen();
}
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Data;
using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Model.Metadata.Annotation;
namespace Snap.Hutao.Model.Metadata.Converter;
/// <summary>
/// 战斗属性数值格式化器
/// </summary>
internal class FightPropertyValueFormatter : IValueConverter
{
/// <inheritdoc/>
public object Convert(object value, Type targetType, object parameter, string language)
{
FormatMethod method = ((FightProperty)parameter).GetFormat();
return method switch
{
FormatMethod.Integer => Math.Round((double)value, MidpointRounding.AwayFromZero),
FormatMethod.Percent => string.Format("{0:P1}", value),
_ => value,
};
}
/// <inheritdoc/>
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw Must.NeverHappen();
}
}

View File

@@ -23,4 +23,4 @@ internal class IconConverter : IValueConverter
{
throw Must.NeverHappen();
}
}
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Data;
using Snap.Hutao.Model.Intrinsic;
namespace Snap.Hutao.Model.Metadata.Converter;
/// <summary>
/// 物品等级转换器
/// </summary>
internal class QualityConverter : IValueConverter
{
private const string BaseUrl = "https://static.snapgenshin.com/Bg/UI_{0}.png";
/// <inheritdoc/>
public object Convert(object value, Type targetType, object parameter, string language)
{
string? name = value.ToString();
if (name == nameof(ItemQuality.QUALITY_ORANGE_SP))
{
name = "QUALITY_RED";
}
return new Uri(string.Format(BaseUrl, name));
}
/// <inheritdoc/>
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw Must.NeverHappen();
}
}

View File

@@ -19,5 +19,5 @@ public class LevelParam<TLevel>
/// <summary>
/// 参数
/// </summary>
public IEnumerable<double> Parameters { get; set; } = default!;
public IList<double> Parameters { get; set; } = default!;
}

View File

@@ -9,7 +9,7 @@
<Identity
Name="7f0db578-026f-4e0b-a75b-d5d06bb0a74d"
Publisher="CN=DGP Studio"
Version="1.0.9.0" />
Version="1.0.10.0" />
<Properties>
<DisplayName>胡桃</DisplayName>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,17 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Service.Metadata;
/// <summary>
/// 指示该类为元数据初始化器
/// </summary>
public interface IMetadataInitializer
{
/// <summary>
/// 异步初始化元数据
/// </summary>
/// <param name="token">取消令牌</param>
/// <returns>任务</returns>
Task InitializeInternalAsync(CancellationToken token = default);
}

View File

@@ -21,7 +21,7 @@ namespace Snap.Hutao.Service.Metadata;
/// 元数据服务
/// </summary>
[Injection(InjectAs.Singleton, typeof(IMetadataService))]
internal class MetadataService : IMetadataService, ISupportAsyncInitialization
internal class MetadataService : IMetadataService, IMetadataInitializer, ISupportAsyncInitialization
{
private const string MetaAPIHost = "http://hutao-metadata.snapgenshin.com";
private const string MetaFileName = "Meta.json";
@@ -32,6 +32,11 @@ internal class MetadataService : IMetadataService, ISupportAsyncInitialization
private readonly ILogger<MetadataService> logger;
private readonly IMemoryCache memoryCache;
/// <summary>
/// 用于指示初始化是否完成
/// </summary>
private readonly TaskCompletionSource initializeCompletionSource = new();
private bool isInitialized = false;
/// <summary>
@@ -65,36 +70,23 @@ internal class MetadataService : IMetadataService, ISupportAsyncInitialization
/// <inheritdoc/>
public async ValueTask<bool> InitializeAsync(CancellationToken token = default)
{
if (IsInitialized)
{
return true;
}
metadataContext.EnsureDirectory();
if (metadataContext.FileExists(MetaFileName))
{
IDictionary<string, string>? metaMd5Map;
using (Stream metaFile = metadataContext.OpenRead(MetaFileName))
{
metaMd5Map = await JsonSerializer
.DeserializeAsync<IDictionary<string, string>>(metaFile, options, token)
.ConfigureAwait(false);
}
await CheckMetadataAsync(Must.NotNull(metaMd5Map!), token)
.ConfigureAwait(false);
IsInitialized = true;
}
else
{
IsInitialized = await UpdateMetadataAsync(token)
.ConfigureAwait(false);
}
await initializeCompletionSource.Task;
return IsInitialized;
}
/// <inheritdoc/>
public async Task InitializeInternalAsync(CancellationToken token = default)
{
logger.LogInformation("元数据初始化开始");
metadataContext.EnsureDirectory();
IsInitialized = await UpdateMetadataAsync(token)
.ConfigureAwait(false);
initializeCompletionSource.SetResult();
logger.LogInformation("元数据初始化完成");
}
/// <inheritdoc/>
public async Task<bool> UpdateMetadataAsync(CancellationToken token = default)
{

View File

@@ -3,6 +3,7 @@
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Core.Logging;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.View.Helper;
using Snap.Hutao.View.Page;
@@ -47,6 +48,8 @@ internal class NavigationService : INavigationService
{
navigationView.ItemInvoked -= OnItemInvoked;
navigationView.BackRequested -= OnBackRequested;
navigationView.PaneClosed -= OnPaneStateChanged;
navigationView.PaneOpened -= OnPaneStateChanged;
}
navigationView = Must.NotNull(value!);
@@ -56,6 +59,8 @@ internal class NavigationService : INavigationService
{
navigationView.ItemInvoked += OnItemInvoked;
navigationView.BackRequested += OnBackRequested;
navigationView.PaneClosed += OnPaneStateChanged;
navigationView.PaneOpened += OnPaneStateChanged;
}
}
}
@@ -154,6 +159,8 @@ internal class NavigationService : INavigationService
{
NavigationView = navigationView;
Frame = frame;
NavigationView.IsPaneOpen = LocalSetting.GetValueType(SettingKeys.IsNavPaneOpen, true);
}
private void OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
@@ -175,4 +182,9 @@ internal class NavigationService : INavigationService
SyncSelectedNavigationViewItemWith(Frame.Content.GetType());
}
}
private void OnPaneStateChanged(NavigationView sender, object args)
{
LocalSetting.SetValueType(SettingKeys.IsNavPaneOpen, NavigationView!.IsPaneOpen);
}
}

View File

@@ -28,7 +28,13 @@
</PropertyGroup>
<ItemGroup>
<None Remove="Resource\Icon\UI_BagTabIcon_Avatar.png" />
<None Remove="Resource\Icon\UI_BagTabIcon_Weapon.png" />
<None Remove="Resource\Icon\UI_BtnIcon_ActivityEntry.png" />
<None Remove="Resource\Icon\UI_Icon_Achievement.png" />
<None Remove="Resource\Segoe Fluent Icons.ttf" />
<None Remove="stylecop.json" />
<None Remove="View\Control\ItemIcon.xaml" />
<None Remove="View\Dialog\UserDialog.xaml" />
<None Remove="View\MainView.xaml" />
<None Remove="View\Page\AchievementPage.xaml" />
@@ -53,6 +59,11 @@
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
<Content Include="Resource\Font\Segoe Fluent Icons.ttf" />
<Content Include="Resource\Icon\UI_BagTabIcon_Avatar.png" />
<Content Include="Resource\Icon\UI_BagTabIcon_Weapon.png" />
<Content Include="Resource\Icon\UI_BtnIcon_ActivityEntry.png" />
<Content Include="Resource\Icon\UI_Icon_Achievement.png" />
</ItemGroup>
<ItemGroup>
@@ -153,4 +164,9 @@
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="View\Control\ItemIcon.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,27 @@
<UserControl
x:Class="Snap.Hutao.View.Control.ItemIcon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Snap.Hutao.View.Control"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:shci="using:Snap.Hutao.Control.Image"
xmlns:shmmc="using:Snap.Hutao.Model.Metadata.Converter"
mc:Ignorable="d"
Width="64"
Height="64">
<UserControl.Resources>
<shmmc:IconConverter x:Key="IconConverter"/>
<shmmc:QualityConverter x:Key="QualityConverter"/>
</UserControl.Resources>
<Grid>
<Grid CornerRadius="{StaticResource CompatCornerRadius}">
<shci:CachedImage
Source="{x:Bind Quality,Converter={StaticResource QualityConverter},Mode=OneWay}"/>
<shci:CachedImage
Source="https://static.snapgenshin.com/Bg/UI_ImgSign_ItemIcon.png"/>
<shci:CachedImage
Source="{x:Bind Icon,Mode=OneWay}"/>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,44 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Core;
using Snap.Hutao.Model.Intrinsic;
namespace Snap.Hutao.View.Control;
/// <summary>
/// 物品图标
/// </summary>
public sealed partial class ItemIcon : UserControl
{
private static readonly DependencyProperty QualityProperty = Property<ItemIcon>.Depend(nameof(Quality), ItemQuality.QUALITY_NONE);
private static readonly DependencyProperty IconProperty = Property<ItemIcon>.Depend<Uri>(nameof(Icon));
/// <summary>
/// 构造一个新的物品图标
/// </summary>
public ItemIcon()
{
InitializeComponent();
}
/// <summary>
/// 等阶
/// </summary>
public ItemQuality Quality
{
get => (ItemQuality)GetValue(QualityProperty);
set => SetValue(QualityProperty, value);
}
/// <summary>
/// 图标
/// </summary>
public Uri Icon
{
get => (Uri)GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
}

View File

@@ -8,7 +8,9 @@
xmlns:page="using:Snap.Hutao.View.Page"
xmlns:view="using:Snap.Hutao.View"
mc:Ignorable="d">
<UserControl.Resources>
<Thickness x:Key="NavigationViewContentMargin">0,48,0,0</Thickness>
</UserControl.Resources>
<Grid>
<!-- x:Bind can't get property update here seems like a WinUI 3 bug-->
<NavigationView
@@ -24,19 +26,19 @@
<NavigationViewItem Content="活动" helper:NavHelper.NavigateTo="page:AnnouncementPage">
<NavigationViewItem.Icon>
<FontIcon Glyph="&#xE7C4;"/>
<BitmapIcon UriSource="ms-appx:///Resource/Icon/UI_BtnIcon_ActivityEntry.png"/>
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem Content="成就" helper:NavHelper.NavigateTo="page:AchievementPage">
<NavigationViewItem.Icon>
<FontIcon Glyph="&#xE7C4;"/>
<BitmapIcon UriSource="ms-appx:///Resource/Icon/UI_Icon_Achievement.png"/>
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem Content="角色" helper:NavHelper.NavigateTo="page:WikiAvatarPage">
<NavigationViewItem.Icon>
<FontIcon Glyph="&#xE7C4;"/>
<BitmapIcon UriSource="ms-appx:///Resource/Icon/UI_BagTabIcon_Avatar.png"/>
</NavigationViewItem.Icon>
</NavigationViewItem>

View File

@@ -1,32 +1,206 @@
<Page
x:Class="Snap.Hutao.View.Page.WikiAvatarPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Snap.Hutao.View.Page"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
xmlns:cwuc="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:mxic="using:Microsoft.Xaml.Interactions.Core"
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
xmlns:shc="using:Snap.Hutao.Control"
xmlns:shmmc="using:Snap.Hutao.Model.Metadata.Converter"
xmlns:shvc="using:Snap.Hutao.View.Control"
xmlns:shv="using:Snap.Hutao.ViewModel"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=shv:WikiAvatarViewModel}"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<mxi:Interaction.Behaviors>
<mxic:EventTriggerBehavior EventName="Loaded">
<mxic:InvokeCommandAction Command="{Binding OpenUICommand}"/>
</mxic:EventTriggerBehavior>
</mxi:Interaction.Behaviors>
<Page.Resources>
<shmmc:IconConverter x:Key="IconConverter"/>
<shmmc:FightPropertyConverter x:Key="FightPropertyConverter"/>
<shmmc:FightPropertyValueFormatter x:Key="FightPropertyValueFormatter"/>
<shc:BindingProxy
x:Key="FightPropertyBindingProxy"
DataContext="{Binding Selected.Property.Properties}"/>
<SolidColorBrush
x:Key="SystemControlPageBackgroundChromeLowBrush"
Color="{StaticResource SystemChromeLowColor}"
Opacity="0.2"/>
</Page.Resources>
<Grid>
<SplitView IsPaneOpen="True" DisplayMode="Inline">
<SplitView
IsPaneOpen="True"
DisplayMode="Inline"
OpenPaneLength="374">
<SplitView.Pane>
<ListView
<GridView
SelectionMode="Single"
ItemsSource="{Binding Avatars}"
SelectedItem="{Binding Selected,Mode=TwoWay}"/>
Padding="16,16,0,12"
SelectedItem="{Binding Selected,Mode=TwoWay}">
<GridView.ItemTemplate>
<DataTemplate>
<shvc:ItemIcon
Quality="{Binding Quality,Mode=OneWay}"
Icon="{Binding Icon,Converter={StaticResource IconConverter},Mode=OneWay}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</SplitView.Pane>
<SplitView.Content>
<Grid>
<TextBlock
Text="{Binding Selected.Name}"/>
</Grid>
<ScrollViewer>
<StackPanel Margin="0,0,16,16">
<!--头图-->
<Grid
Margin="16,16,0,16"
VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<shvc:ItemIcon
Grid.Column="0"
Height="100"
Width="100"
Quality="{Binding Selected.Quality,Mode=OneWay}"
Icon="{Binding Selected.Icon,Converter={StaticResource IconConverter},Mode=OneWay}"/>
<StackPanel
Margin="16,0,0,0"
Grid.Column="1">
<TextBlock
Text="{Binding Selected.Name}"
Style="{StaticResource SubtitleTextBlockStyle}"/>
<TextBlock
Margin="0,6,0,0"
Text="{Binding Selected.Description}"
MaxLines="2"
Style="{StaticResource CaptionTextBlockStyle}"/>
</StackPanel>
</Grid>
<!--属性-->
<Expander
Margin="16,0,0,0"
Header="基础数值"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<cwuc:UniformGrid
Grid.Row="0"
Columns="5"
DataContext="{Binding Selected.Property}"
x:Name="PropertyGrid">
<TextBlock
Style="{StaticResource BaseTextBlockStyle}"
TextWrapping="NoWrap"
Text="等级"/>
<TextBlock
TextWrapping="NoWrap"
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding Properties[0], Converter={StaticResource FightPropertyConverter}}"/>
<TextBlock
TextWrapping="NoWrap"
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding Properties[1], Converter={StaticResource FightPropertyConverter}}"/>
<TextBlock
TextWrapping="NoWrap"
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding Properties[2], Converter={StaticResource FightPropertyConverter}}"/>
<TextBlock
TextWrapping="NoWrap"
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding Properties[3], Converter={StaticResource FightPropertyConverter}}"/>
</cwuc:UniformGrid>
<ItemsControl
Margin="0,6,0,0"
Grid.Row="1"
ItemsSource="{Binding Selected.Property.Parameters}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<cwuc:UniformGrid
Columns="5">
<TextBlock
Text="{Binding Level}"/>
<TextBlock
Text="{Binding Parameters[0],
Converter={StaticResource FightPropertyValueFormatter},
ConverterParameter={Binding DataContext[0],Source={StaticResource FightPropertyBindingProxy}}}"/>
<TextBlock
Text="{Binding Parameters[1],
Converter={StaticResource FightPropertyValueFormatter},
ConverterParameter={Binding DataContext[1],Source={StaticResource FightPropertyBindingProxy}}}"/>
<TextBlock
Text="{Binding Parameters[2],
Converter={StaticResource FightPropertyValueFormatter},
ConverterParameter={Binding DataContext[2],Source={StaticResource FightPropertyBindingProxy}}}"/>
<TextBlock
Text="{Binding Parameters[3],
Converter={StaticResource FightPropertyValueFormatter},
ConverterParameter={Binding DataContext[3],Source={StaticResource FightPropertyBindingProxy}}}"/>
</cwuc:UniformGrid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Expander>
<!--资料-->
<Expander
Margin="16,16,0,0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Header="语音">
<ItemsControl
ItemsSource="{Binding Selected.FetterInfo.Fetters}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,-4">
<TextBlock
Margin="16,16,16,0"
Text="{Binding Title}"/>
<TextBlock
Margin="16,8,16,16"
Text="{Binding Context}"
Style="{StaticResource CaptionTextBlockStyle}"/>
<MenuFlyoutSeparator Margin="16,0"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Expander>
<!--故事-->
<Expander
Margin="16,16,0,0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Header="故事">
<ItemsControl
ItemsSource="{Binding Selected.FetterInfo.FetterStories}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,-4">
<TextBlock
Margin="16,16,16,0"
Text="{Binding Title}"/>
<TextBlock
Margin="16,8,16,16"
Text="{Binding Context}"
Style="{StaticResource CaptionTextBlockStyle}"/>
<MenuFlyoutSeparator Margin="16,0"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Expander>
</StackPanel>
</ScrollViewer>
</SplitView.Content>
</SplitView>
</Grid>

View File

@@ -1,21 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Snap.Hutao.ViewModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
namespace Snap.Hutao.View.Page;

View File

@@ -13,6 +13,6 @@
TextWrapping="NoWrap"
Style="{StaticResource CaptionTextBlockStyle}"
VerticalAlignment="Center"
Margin="12,0,0,0"/>
Margin="4,0,0,0"/>
</Grid>
</UserControl>

View File

@@ -6,6 +6,7 @@ using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model.Metadata.Avatar;
using Snap.Hutao.Service.Metadata;
using System.Collections.Generic;
using System.Linq;
namespace Snap.Hutao.ViewModel;
@@ -51,7 +52,12 @@ internal class WikiAvatarViewModel : ObservableObject
if (await metadataService.InitializeAsync())
{
IEnumerable<Avatar>? avatars = await metadataService.GetAvatarsAsync();
Avatars = new List<Avatar>(avatars);
IOrderedEnumerable<Avatar> sorted = avatars
.OrderBy(avatar => avatar.BeginTime)
.ThenBy(avatar => avatar.Sort);
Avatars = new List<Avatar>(sorted);
Selected = Avatars[0];
}
}
}