mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
move extensions
This commit is contained in:
@@ -1,16 +1,19 @@
|
||||
# Snap.Hutao
|
||||
> 唷,找本堂主有何贵干呀?
|
||||
|
||||

|
||||

|
||||
|
||||
## 感谢以下项目或人员的帮助
|
||||
## Special Thanks
|
||||
|
||||
* [biuuu/genshin-wish-export](https://github.com/biuuu/genshin-wish-export)
|
||||
* [CommunityToolkit/dotnet](https://github.com/CommunityToolkit/dotnet)
|
||||
* [CommunityToolkit/WindowsCommunityToolkit](https://github.com/CommunityToolkit/WindowsCommunityToolkit)
|
||||
* [dotnet/efcore](https://github.com/dotnet/efcore)
|
||||
* [dotnet/runtime](https://github.com/dotnet/runtime)
|
||||
* [HolographicHat/YaeAchievement](https://github.com/HolographicHat/YaeAchievement)
|
||||
* [DotNetAnalyzers/StyleCopAnalyzers](https://github.com/DotNetAnalyzers/StyleCopAnalyzers)
|
||||
* [microsoft/vs-threading](https://github.com/microsoft/vs-threading)
|
||||
* [microsoft/vs-validation](https://github.com/microsoft/vs-validation)
|
||||
* [microsoft/WindowsAppSDK](https://github.com/microsoft/WindowsAppSDK)
|
||||
* [microsoft/microsoft-ui-xaml](https://github.com/microsoft/microsoft-ui-xaml)
|
||||
* [microsoft/microsoft-ui-xaml](https://github.com/microsoft/microsoft-ui-xaml)
|
||||
* [YuehaiTeam/cocogoat](https://github.com/YuehaiTeam/cocogoat)
|
||||
@@ -5,7 +5,7 @@ using Microsoft.Graphics.Canvas.Effects;
|
||||
using Microsoft.UI.Composition;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Snap.Hutao.Extension;
|
||||
namespace Snap.Hutao.Control.Image;
|
||||
|
||||
/// <summary>
|
||||
/// 合成扩展
|
||||
@@ -4,7 +4,6 @@
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Composition;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Snap.Hutao.Extension;
|
||||
using System.Numerics;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.Storage;
|
||||
|
||||
@@ -6,7 +6,6 @@ using Microsoft.UI;
|
||||
using Microsoft.UI.Composition;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Snap.Hutao.Extension;
|
||||
|
||||
namespace Snap.Hutao.Control.Image;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
|
||||
namespace Snap.Hutao.Extension;
|
||||
namespace Snap.Hutao.Core.LifeCycle;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="AppActivationArguments"/> 扩展
|
||||
@@ -4,7 +4,7 @@
|
||||
using Microsoft.UI.Windowing;
|
||||
using Windows.Graphics;
|
||||
|
||||
namespace Snap.Hutao.Extension;
|
||||
namespace Snap.Hutao.Core.Windowing;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="AppWindow"/> 扩展
|
||||
@@ -4,7 +4,6 @@
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Snap.Hutao.Core.Setting;
|
||||
using Snap.Hutao.Extension;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Graphics;
|
||||
using Windows.Win32.Foundation;
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace Snap.Hutao.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// 反射扩展
|
||||
/// </summary>
|
||||
internal static class ReflectionExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 在指定的成员中尝试获取标记的特性
|
||||
/// </summary>
|
||||
/// <typeparam name="TAttribute">特性的类型</typeparam>
|
||||
/// <param name="type">类型</param>
|
||||
/// <param name="attribute">获取的特性</param>
|
||||
/// <returns>是否获取成功</returns>
|
||||
public static bool TryGetAttribute<TAttribute>(this Type type, [NotNullWhen(true)] out TAttribute? attribute)
|
||||
where TAttribute : Attribute
|
||||
{
|
||||
attribute = type.GetCustomAttribute<TAttribute>();
|
||||
return attribute != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测类型是否实现接口
|
||||
/// </summary>
|
||||
/// <typeparam name="TInterface">被实现的类型</typeparam>
|
||||
/// <param name="type">被检测的类型/param>
|
||||
/// <returns>是否实现接口</returns>
|
||||
[SuppressMessage("", "SA1615")]
|
||||
public static bool Implement<TInterface>(this Type type)
|
||||
{
|
||||
return type.IsAssignableTo(typeof(TInterface));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查程序集是否标记了指定的特性
|
||||
/// </summary>
|
||||
/// <typeparam name="TAttribute">特性类型</typeparam>
|
||||
/// <param name="assembly">指定的程序集</param>
|
||||
/// <returns>是否标记了指定的特性</returns>
|
||||
public static bool HasAttribute<TAttribute>(this Assembly assembly)
|
||||
where TAttribute : Attribute
|
||||
{
|
||||
return assembly.GetCustomAttribute<TAttribute>() is not null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对程序集中的所有类型进行指定的操作
|
||||
/// </summary>
|
||||
/// <param name="assembly">指定的程序集</param>
|
||||
/// <param name="action">进行的操作</param>
|
||||
public static void ForEachType(this Assembly assembly, Action<Type> action)
|
||||
{
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
action.Invoke(type);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按字段名称设置值
|
||||
/// </summary>
|
||||
/// <param name="obj">对象</param>
|
||||
/// <param name="fieldName">字段名称</param>
|
||||
/// <param name="value">值</param>
|
||||
public static void SetPrivateFieldValueByName(this object obj, string fieldName, object? value)
|
||||
{
|
||||
FieldInfo? fieldInfo = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
fieldInfo?.SetValue(obj, value);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Snap.Hutao.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// 元组扩展
|
||||
/// </summary>
|
||||
public static class TupleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 将二项元组转化为一个单项的字典
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">键类型</typeparam>
|
||||
/// <typeparam name="TValue">值类型</typeparam>
|
||||
/// <param name="tuple">元组</param>
|
||||
/// <returns>仅包含一个项的字典</returns>
|
||||
public static IDictionary<TKey, TValue> AsDictionary<TKey, TValue>(this (TKey Key, TValue Value) tuple)
|
||||
where TKey : notnull
|
||||
{
|
||||
return new Dictionary<TKey, TValue>(1) { { tuple.Key, tuple.Value } };
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public sealed partial class MainWindow : Window
|
||||
this.messenger = messenger;
|
||||
|
||||
InitializeComponent();
|
||||
windowManager = new WindowManager(this, TitleBarView.DragableArea);
|
||||
windowManager = new WindowManager(this, TitleBarView.DragArea);
|
||||
|
||||
initializaionCompletionSource.TrySetResult();
|
||||
}
|
||||
|
||||
@@ -57,7 +57,16 @@ public class Achievement : Observable
|
||||
{
|
||||
Entity.Status = Intrinsic.AchievementInfoStatus.ACHIEVEMENT_POINT_TAKEN;
|
||||
Entity.Time = DateTimeOffset.Now;
|
||||
OnPropertyChanged(nameof(Time));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化的时间
|
||||
/// </summary>
|
||||
public string Time
|
||||
{
|
||||
get => entity.Time.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,14 @@
|
||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||
xmlns:shmmc="using:Snap.Hutao.Model.Metadata.Converter"
|
||||
xmlns:shv="using:Snap.Hutao.ViewModel"
|
||||
xmlns:cwuc="using:CommunityToolkit.WinUI.UI.Converters"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
d:DataContext="{d:DesignInstance shv:AchievementViewModel}">
|
||||
|
||||
<shcc:CancellablePage.Resources>
|
||||
<shmmc:AchievementIconConverter x:Key="AchievementIconConverter"/>
|
||||
<cwuc:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||
</shcc:CancellablePage.Resources>
|
||||
|
||||
<mxi:Interaction.Behaviors>
|
||||
@@ -86,8 +88,11 @@
|
||||
<FontIcon Glyph=""/>
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
<AppBarSeparator/>
|
||||
<AppBarToggleButton
|
||||
Label="优先未完成">
|
||||
Label="优先未完成"
|
||||
IsChecked="{Binding IsIncompletedItemsFirst}"
|
||||
Command="{Binding SortIncompletedSwitchCommand}">
|
||||
<AppBarToggleButton.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</AppBarToggleButton.Icon>
|
||||
@@ -163,7 +168,7 @@
|
||||
|
||||
<CheckBox
|
||||
IsChecked="{Binding IsChecked,Mode=TwoWay}"
|
||||
Margin="6,0,0,0"
|
||||
Margin="6,0,12,0"
|
||||
Style="{StaticResource DefaultCheckBoxStyle}"
|
||||
Padding="16,0,0,0"
|
||||
Grid.Column="1">
|
||||
@@ -173,22 +178,32 @@
|
||||
<TextBlock
|
||||
Margin="0,2,0,0"
|
||||
Style="{StaticResource SecondaryTextStyle}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Text="{Binding Inner.Description}"/>
|
||||
</StackPanel>
|
||||
</CheckBox.Content>
|
||||
</CheckBox>
|
||||
<Grid Grid.Column="3">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="32"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="12,0,12,0"
|
||||
VerticalAlignment="Center"
|
||||
Grid.Column="0"
|
||||
Text="{Binding Time}"
|
||||
Visibility="{Binding IsChecked,Converter={StaticResource BoolToVisibilityConverter}}"
|
||||
/>
|
||||
<Image
|
||||
Grid.Column="1"
|
||||
Height="32"
|
||||
Source="ms-appx:///Resource/Icon/UI_ItemIcon_201.png"/>
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Grid.Column="1"
|
||||
Grid.Column="2"
|
||||
Text="{Binding Inner.FinishReward.Count}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
Height="44">
|
||||
<Grid x:Name="DragableGrid">
|
||||
<TextBlock
|
||||
Text="胡桃"
|
||||
Text="{x:Bind Title}"
|
||||
TextWrapping="NoWrap"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
VerticalAlignment="Center"
|
||||
|
||||
@@ -22,8 +22,13 @@ public sealed partial class TitleView : UserControl
|
||||
/// <summary>
|
||||
/// 获取可拖动区域
|
||||
/// </summary>
|
||||
public FrameworkElement DragableArea
|
||||
public FrameworkElement DragArea
|
||||
{
|
||||
get => DragableGrid;
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => $"胡桃 {Core.CoreEnvironment.Version}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.WinUI.UI;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
@@ -41,6 +42,8 @@ internal class AchievementViewModel
|
||||
IRecipient<AchievementArchiveChangedMessage>,
|
||||
IRecipient<MainWindowClosedMessage>
|
||||
{
|
||||
private static readonly SortDescription IncompletedItemsFirstSortDescription = new(nameof(Model.Binding.Achievement.IsChecked), SortDirection.Ascending);
|
||||
|
||||
private readonly IMetadataService metadataService;
|
||||
private readonly IAchievementService achievementService;
|
||||
private readonly IInfoBarService infoBarService;
|
||||
@@ -54,6 +57,7 @@ internal class AchievementViewModel
|
||||
private AchievementGoal? selectedAchievementGoal;
|
||||
private ObservableCollection<Model.Entity.AchievementArchive>? archives;
|
||||
private Model.Entity.AchievementArchive? selectedArchive;
|
||||
private bool isIncompletedItemsFirst = true;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的成就视图模型
|
||||
@@ -85,6 +89,7 @@ internal class AchievementViewModel
|
||||
ImportUIAFFromFileCommand = asyncRelayCommandFactory.Create(ImportUIAFFromFileAsync);
|
||||
AddArchiveCommand = asyncRelayCommandFactory.Create(AddArchiveAsync);
|
||||
RemoveArchiveCommand = asyncRelayCommandFactory.Create(RemoveArchiveAsync);
|
||||
SortIncompletedSwitchCommand = new RelayCommand(UpdateAchievementsSort);
|
||||
|
||||
messenger.Register<AchievementArchiveChangedMessage>(this);
|
||||
messenger.Register<MainWindowClosedMessage>(this);
|
||||
@@ -148,6 +153,15 @@ internal class AchievementViewModel
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 未完成优先
|
||||
/// </summary>
|
||||
public bool IsIncompletedItemsFirst
|
||||
{
|
||||
get => isIncompletedItemsFirst;
|
||||
set => SetProperty(ref isIncompletedItemsFirst, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开页面命令
|
||||
/// </summary>
|
||||
@@ -173,6 +187,11 @@ internal class AchievementViewModel
|
||||
/// </summary>
|
||||
public ICommand ImportUIAFFromFileCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 筛选未完成项开关命令
|
||||
/// </summary>
|
||||
public ICommand SortIncompletedSwitchCommand { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Receive(MainWindowClosedMessage message)
|
||||
{
|
||||
@@ -264,6 +283,7 @@ internal class AchievementViewModel
|
||||
Achievements = new(combined, true);
|
||||
|
||||
UpdateAchievementFilter(SelectedAchievementGoal);
|
||||
UpdateAchievementsSort();
|
||||
}
|
||||
|
||||
private async Task AddArchiveAsync()
|
||||
@@ -443,6 +463,21 @@ internal class AchievementViewModel
|
||||
return false;
|
||||
}
|
||||
|
||||
private void UpdateAchievementsSort()
|
||||
{
|
||||
if (Achievements != null)
|
||||
{
|
||||
if (IsIncompletedItemsFirst)
|
||||
{
|
||||
Achievements.SortDescriptions.Add(IncompletedItemsFirstSortDescription);
|
||||
}
|
||||
else
|
||||
{
|
||||
Achievements.SortDescriptions.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAchievementFilter(AchievementGoal? goal)
|
||||
{
|
||||
if (Achievements != null)
|
||||
|
||||
Reference in New Issue
Block a user