mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
gacha part 1
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
|
||||
namespace Snap.Hutao.Control.Markup;
|
||||
|
||||
/// <summary>
|
||||
/// Custom <see cref="Markup"/> which can provide <see cref="BitmapIcon"/> values.
|
||||
/// </summary>
|
||||
[MarkupExtensionReturnType(ReturnType = typeof(BitmapIcon))]
|
||||
public sealed class BitmapIconExtension : MarkupExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Uri"/> representing the image to display.
|
||||
/// </summary>
|
||||
public Uri Source { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to display the icon as monochrome.
|
||||
/// </summary>
|
||||
public bool ShowAsMonochrome { get; set; } = true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override object ProvideValue()
|
||||
{
|
||||
return new BitmapIcon
|
||||
{
|
||||
ShowAsMonochrome = ShowAsMonochrome,
|
||||
UriSource = Source,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
|
||||
namespace Snap.Hutao.Control.Markup;
|
||||
|
||||
/// <summary>
|
||||
/// Custom <see cref="Microsoft.UI.Xaml.Markup.MarkupExtension"/> which can provide <see cref="FontIcon"/> values.
|
||||
/// </summary>
|
||||
[MarkupExtensionReturnType(ReturnType = typeof(FontIcon))]
|
||||
internal class FontIconExtension : MarkupExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="string"/> value representing the icon to display.
|
||||
/// </summary>
|
||||
public string Glyph { get; set; } = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override object ProvideValue()
|
||||
{
|
||||
return new FontIcon()
|
||||
{
|
||||
Glyph = Glyph,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ namespace Snap.Hutao.Core.Database;
|
||||
|
||||
/// <summary>
|
||||
/// 数据库当前项
|
||||
/// 简化对数据库中选中项的管理
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">实体的类型</typeparam>
|
||||
/// <typeparam name="TMessage">消息的类型</typeparam>
|
||||
@@ -35,7 +36,7 @@ internal class DbCurrent<TEntity, TMessage>
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前项
|
||||
/// 当前选中的项
|
||||
/// </summary>
|
||||
public TEntity? Current
|
||||
{
|
||||
|
||||
@@ -58,6 +58,40 @@ internal sealed class WindowManager : IDisposable
|
||||
subclassManager?.Dispose();
|
||||
}
|
||||
|
||||
private static void UpdateTitleButtonColor(AppWindowTitleBar appTitleBar)
|
||||
{
|
||||
appTitleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||
appTitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||
|
||||
App app = Ioc.Default.GetRequiredService<App>();
|
||||
|
||||
Color systemBaseLowColor = (Color)app.Resources["SystemBaseLowColor"];
|
||||
appTitleBar.ButtonHoverBackgroundColor = systemBaseLowColor;
|
||||
|
||||
Color systemBaseMediumLowColor = (Color)app.Resources["SystemBaseMediumLowColor"];
|
||||
appTitleBar.ButtonPressedBackgroundColor = systemBaseMediumLowColor;
|
||||
|
||||
// The Foreground doesn't accept Alpha channel. So we translate it to gray.
|
||||
byte light = (byte)((systemBaseMediumLowColor.R + systemBaseMediumLowColor.G + systemBaseMediumLowColor.B) / 3);
|
||||
byte result = (byte)((systemBaseMediumLowColor.A / 255.0) * light);
|
||||
appTitleBar.ButtonInactiveForegroundColor = Color.FromArgb(0xFF, result, result, result);
|
||||
|
||||
Color systemBaseHighColor = (Color)app.Resources["SystemBaseHighColor"];
|
||||
appTitleBar.ButtonForegroundColor = systemBaseHighColor;
|
||||
appTitleBar.ButtonHoverForegroundColor = systemBaseHighColor;
|
||||
appTitleBar.ButtonPressedForegroundColor = systemBaseHighColor;
|
||||
}
|
||||
|
||||
private static (string PosString, string SizeString) GetPostionAndSize(AppWindow appWindow)
|
||||
{
|
||||
PointInt32 pos = appWindow.Position;
|
||||
string posString = $"{pos.X},{pos.Y}";
|
||||
SizeInt32 size = appWindow.Size;
|
||||
string sizeString = $"{size.Width},{size.Height}";
|
||||
|
||||
return (posString, sizeString);
|
||||
}
|
||||
|
||||
private void InitializeWindow()
|
||||
{
|
||||
appWindow.Title = "胡桃";
|
||||
@@ -66,11 +100,8 @@ internal sealed class WindowManager : IDisposable
|
||||
Persistence.RecoverOrInit(appWindow);
|
||||
|
||||
// Log basic window state here.
|
||||
PointInt32 pos = appWindow.Position;
|
||||
string posString = $"{pos.X},{pos.Y}";
|
||||
SizeInt32 size = appWindow.Size;
|
||||
string sizeString = $"{size.Width},{size.Height}";
|
||||
logger.LogInformation(EventIds.WindowState, "Postion: [{pos}], Size: [{size}]", posString, sizeString);
|
||||
(string pos, string size) = GetPostionAndSize(appWindow);
|
||||
logger.LogInformation(EventIds.WindowState, "Postion: [{pos}], Size: [{size}]", pos, size);
|
||||
|
||||
appWindow.Show(true);
|
||||
|
||||
@@ -116,29 +147,4 @@ internal sealed class WindowManager : IDisposable
|
||||
|
||||
appTitleBar.SetDragRectangles(dragRects);
|
||||
}
|
||||
|
||||
[SuppressMessage("", "CA1822")]
|
||||
private void UpdateTitleButtonColor(AppWindowTitleBar appTitleBar)
|
||||
{
|
||||
appTitleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||
appTitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||
|
||||
App app = Ioc.Default.GetRequiredService<App>();
|
||||
|
||||
Color systemBaseLowColor = (Color)app.Resources["SystemBaseLowColor"];
|
||||
appTitleBar.ButtonHoverBackgroundColor = systemBaseLowColor;
|
||||
|
||||
Color systemBaseMediumLowColor = (Color)app.Resources["SystemBaseMediumLowColor"];
|
||||
appTitleBar.ButtonPressedBackgroundColor = systemBaseMediumLowColor;
|
||||
|
||||
// The Foreground doesn't accept Alpha channel. So we translate it to gray.
|
||||
byte light = (byte)((systemBaseMediumLowColor.R + systemBaseMediumLowColor.G + systemBaseMediumLowColor.B) / 3);
|
||||
byte result = (byte)((systemBaseMediumLowColor.A / 255.0) * light);
|
||||
appTitleBar.ButtonInactiveForegroundColor = Color.FromArgb(0xFF, result, result, result);
|
||||
|
||||
Color systemBaseHighColor = (Color)app.Resources["SystemBaseHighColor"];
|
||||
appTitleBar.ButtonForegroundColor = systemBaseHighColor;
|
||||
appTitleBar.ButtonHoverForegroundColor = systemBaseHighColor;
|
||||
appTitleBar.ButtonPressedForegroundColor = systemBaseHighColor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Entity;
|
||||
|
||||
namespace Snap.Hutao.Message;
|
||||
|
||||
/// <summary>
|
||||
/// 祈愿记录存档切换消息
|
||||
/// </summary>
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
|
||||
internal class GachaArchiveChangedMessage : ValueChangedMessage<GachaArchive>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的用户切换消息
|
||||
/// </summary>
|
||||
/// <param name="oldArchive">老用户</param>
|
||||
/// <param name="newArchive">新用户</param>
|
||||
public GachaArchiveChangedMessage(GachaArchive? oldArchive, GachaArchive? newArchive)
|
||||
: base(oldArchive, newArchive)
|
||||
{
|
||||
}
|
||||
}
|
||||
11
src/Snap.Hutao/Snap.Hutao/Model/Binding/GachaStatistics.cs
Normal file
11
src/Snap.Hutao/Snap.Hutao/Model/Binding/GachaStatistics.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Binding;
|
||||
|
||||
/// <summary>
|
||||
/// 祈愿统计
|
||||
/// </summary>
|
||||
public class GachaStatistics
|
||||
{
|
||||
}
|
||||
@@ -15,7 +15,7 @@ public class User : Observable
|
||||
private readonly Entity.User inner;
|
||||
|
||||
private UserGameRole? selectedUserGameRole;
|
||||
private bool isInitialized = false;
|
||||
private bool isInitialized;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的绑定视图用户
|
||||
@@ -105,4 +105,4 @@ public class User : Observable
|
||||
|
||||
return UserInfo != null && UserGameRoles.Any();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ namespace Snap.Hutao.Model.InterChange.Achievement;
|
||||
|
||||
/// <summary>
|
||||
/// 统一可交换成就格式
|
||||
/// https://www.snapgenshin.com/development/UIAF.html
|
||||
/// </summary>
|
||||
public class UIAF
|
||||
{
|
||||
|
||||
37
src/Snap.Hutao/Snap.Hutao/Model/InterChange/GachaLog/UIGF.cs
Normal file
37
src/Snap.Hutao/Snap.Hutao/Model/InterChange/GachaLog/UIGF.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.InterChange.GachaLog;
|
||||
|
||||
/// <summary>
|
||||
/// 统一可交换祈愿格式
|
||||
/// https://www.snapgenshin.com/development/UIGF.html
|
||||
/// </summary>
|
||||
public class UIGF
|
||||
{
|
||||
private static readonly List<string> SupportedVersion = new()
|
||||
{
|
||||
"v2.2",
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 信息
|
||||
/// </summary>
|
||||
[JsonPropertyName("info")]
|
||||
public UIGFInfo Info { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 列表
|
||||
/// </summary>
|
||||
[JsonPropertyName("list")]
|
||||
public List<UIGFItem> List { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 确认当前UIGF对象的版本是否受支持
|
||||
/// </summary>
|
||||
/// <returns>当前UIAF对象是否受支持</returns>
|
||||
public bool IsCurrentVersionSupported()
|
||||
{
|
||||
return SupportedVersion.Contains(Info.UIGFVersion ?? string.Empty);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Extension;
|
||||
|
||||
namespace Snap.Hutao.Model.InterChange.GachaLog;
|
||||
|
||||
/// <summary>
|
||||
/// UIGF格式的信息
|
||||
/// </summary>
|
||||
public class UIGFInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户Uid
|
||||
/// </summary>
|
||||
[JsonPropertyName("uid")]
|
||||
public string Uid { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 语言
|
||||
/// </summary>
|
||||
[JsonPropertyName("lang")]
|
||||
public string Language { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 导出的时间戳
|
||||
/// </summary>
|
||||
[JsonPropertyName("export_timestamp")]
|
||||
public long? ExportTimestamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 导出时间
|
||||
/// </summary>
|
||||
public DateTimeOffset ExportDateTime
|
||||
{
|
||||
get => DateTimeOffsetExtensions.FromUnixTime(ExportTimestamp, DateTimeOffset.MinValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出的 App 名称
|
||||
/// </summary>
|
||||
[JsonPropertyName("export_app")]
|
||||
public string ExportApp { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 导出的 App 版本
|
||||
/// </summary>
|
||||
[JsonPropertyName("export_app_version")]
|
||||
public string ExportAppVersion { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 使用的UIGF版本
|
||||
/// </summary>
|
||||
[JsonPropertyName("uigf_version")]
|
||||
public string UIGFVersion { get; set; } = default!;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using MiniExcelLibs.Attributes;
|
||||
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
|
||||
|
||||
namespace Snap.Hutao.Model.InterChange.GachaLog;
|
||||
|
||||
/// <summary>
|
||||
/// UIGF物品
|
||||
/// </summary>
|
||||
public class UIGFItem : GachaLogItem
|
||||
{
|
||||
/// <summary>
|
||||
/// 额外祈愿映射
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "uigf_gacha_type")]
|
||||
[JsonPropertyName("uigf_gacha_type")]
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public GachaConfigType UIGFGachaType { get; set; } = default!;
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Snap.Hutao.Context.Database;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Snap.Hutao.Service.GachaLog;
|
||||
|
||||
/// <summary>
|
||||
@@ -9,10 +15,32 @@ namespace Snap.Hutao.Service.GachaLog;
|
||||
[Injection(InjectAs.Transient, typeof(IGachaLogService))]
|
||||
internal class GachaLogService : IGachaLogService
|
||||
{
|
||||
public GachaLogService()
|
||||
{
|
||||
private readonly AppDbContext appDbContext;
|
||||
private readonly DbCurrent<GachaArchive, Message.GachaArchiveChangedMessage> dbCurrent;
|
||||
|
||||
private ObservableCollection<GachaArchive>? archiveCollection;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的祈愿记录服务
|
||||
/// </summary>
|
||||
/// <param name="appDbContext">数据库上下文</param>
|
||||
/// <param name="messenger">消息器</param>
|
||||
public GachaLogService(AppDbContext appDbContext, IMessenger messenger)
|
||||
{
|
||||
this.appDbContext = appDbContext;
|
||||
dbCurrent = new(appDbContext, appDbContext.GachaArchives, messenger);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public GachaArchive? CurrentArchive
|
||||
{
|
||||
get => dbCurrent.Current;
|
||||
set => dbCurrent.Current = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ObservableCollection<GachaArchive> GetArchiveCollection()
|
||||
{
|
||||
return archiveCollection ??= new(appDbContext.GachaArchives.ToList());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Snap.Hutao.Service.GachaLog;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,5 +11,14 @@ namespace Snap.Hutao.Service.GachaLog;
|
||||
/// </summary>
|
||||
internal interface IGachaLogService
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前存档
|
||||
/// </summary>
|
||||
GachaArchive? CurrentArchive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取可用于绑定的存档集合
|
||||
/// </summary>
|
||||
/// <returns>存档集合</returns>
|
||||
ObservableCollection<GachaArchive> GetArchiveCollection();
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ internal class MetadataService : IMetadataService, IMetadataInitializer, ISuppor
|
||||
/// </summary>
|
||||
private readonly TaskCompletionSource initializeCompletionSource = new();
|
||||
|
||||
private bool isInitialized = false;
|
||||
private bool isInitialized;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的元数据服务
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.1" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.1.4" />
|
||||
<PackageReference Include="MiniExcel" Version="1.26.7" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
@@ -203,7 +204,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Web\Hoyolab\Takumi\Event\" />
|
||||
<Folder Include="Win32\UI\WindowsAndMessaging\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="View\Page\GachaLogPage.xaml">
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
xmlns:shv="using:Snap.Hutao.View"
|
||||
xmlns:shvh="using:Snap.Hutao.View.Helper"
|
||||
xmlns:shvp="using:Snap.Hutao.View.Page"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<Thickness x:Key="NavigationViewContentMargin">0,44,0,0</Thickness>
|
||||
@@ -24,22 +25,22 @@
|
||||
<NavigationViewItem
|
||||
Content="活动"
|
||||
shvh:NavHelper.NavigateTo="shvp:AnnouncementPage"
|
||||
Icon="{cwu:BitmapIcon ShowAsMonochrome=True,Source=ms-appx:///Resource/Icon/UI_BtnIcon_ActivityEntry.png}"/>
|
||||
Icon="{shcm:BitmapIcon Source=ms-appx:///Resource/Icon/UI_BtnIcon_ActivityEntry.png}"/>
|
||||
|
||||
<NavigationViewItem
|
||||
Content="成就"
|
||||
shvh:NavHelper.NavigateTo="shvp:AchievementPage"
|
||||
Icon="{cwu:BitmapIcon ShowAsMonochrome=True,Source=ms-appx:///Resource/Icon/UI_Icon_Achievement.png}"/>
|
||||
Icon="{shcm:BitmapIcon Source=ms-appx:///Resource/Icon/UI_Icon_Achievement.png}"/>
|
||||
|
||||
<NavigationViewItem
|
||||
Content="角色"
|
||||
shvh:NavHelper.NavigateTo="shvp:WikiAvatarPage"
|
||||
Icon="{cwu:BitmapIcon ShowAsMonochrome=True,Source=ms-appx:///Resource/Icon/UI_BagTabIcon_Avatar.png}"/>
|
||||
Icon="{shcm:BitmapIcon Source=ms-appx:///Resource/Icon/UI_BagTabIcon_Avatar.png}"/>
|
||||
|
||||
<NavigationViewItem
|
||||
Content="祈愿记录"
|
||||
shvh:NavHelper.NavigateTo="shvp:GachaLogPage"
|
||||
Icon="{cwu:BitmapIcon ShowAsMonochrome=True,Source=ms-appx:///Resource/Icon/UI_BtnIcon_Gacha.png}"/>
|
||||
Icon="{shcm:BitmapIcon Source=ms-appx:///Resource/Icon/UI_BtnIcon_Gacha.png}"/>
|
||||
</NavigationView.MenuItems>
|
||||
|
||||
<NavigationView.PaneFooter>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||
xmlns:shmmc="using:Snap.Hutao.Model.Metadata.Converter"
|
||||
xmlns:shv="using:Snap.Hutao.ViewModel"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
xmlns:cwuc="using:CommunityToolkit.WinUI.UI.Converters"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
@@ -37,7 +38,6 @@
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<CommandBar
|
||||
|
||||
Grid.Column="1"
|
||||
DefaultLabelPosition="Right">
|
||||
<CommandBar.Content>
|
||||
@@ -61,42 +61,37 @@
|
||||
</AppBarElementContainer>
|
||||
<AppBarButton
|
||||
Label="创建新存档"
|
||||
Command="{Binding AddArchiveCommand}">
|
||||
<AppBarButton.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
Icon="{shcm:FontIcon Glyph=}"
|
||||
Command="{Binding AddArchiveCommand}"/>
|
||||
<AppBarButton
|
||||
Label="删除当前存档"
|
||||
Command="{Binding RemoveArchiveCommand}">
|
||||
<AppBarButton.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
Icon="{shcm:FontIcon Glyph=}"
|
||||
Command="{Binding RemoveArchiveCommand}"/>
|
||||
|
||||
<AppBarSeparator/>
|
||||
|
||||
<AppBarButton
|
||||
Label="从剪贴板导入"
|
||||
Command="{Binding ImportUIAFFromClipboardCommand}">
|
||||
<AppBarButton.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</AppBarButton.Icon>
|
||||
</AppBarButton>
|
||||
<AppBarButton
|
||||
Label="从UIAF文件导入"
|
||||
Command="{Binding ImportUIAFFromFileCommand}">
|
||||
<AppBarButton.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</AppBarButton.Icon>
|
||||
Label="导入"
|
||||
Icon="{shcm:FontIcon Glyph=}">
|
||||
<AppBarButton.Flyout>
|
||||
<MenuFlyout Placement="BottomEdgeAlignedRight">
|
||||
<MenuFlyoutItem
|
||||
Text="从剪贴板导入"
|
||||
Icon="{shcm:FontIcon Glyph=}"
|
||||
Command="{Binding ImportUIAFFromClipboardCommand}"/>
|
||||
<MenuFlyoutItem
|
||||
Text="从 UIAF 文件导入"
|
||||
Icon="{shcm:FontIcon Glyph=}"
|
||||
Command="{Binding ImportUIAFFromFileCommand}"/>
|
||||
</MenuFlyout>
|
||||
</AppBarButton.Flyout>
|
||||
</AppBarButton>
|
||||
<AppBarSeparator/>
|
||||
<AppBarToggleButton
|
||||
Label="优先未完成"
|
||||
Icon="{shcm:FontIcon Glyph=}"
|
||||
IsChecked="{Binding IsIncompletedItemsFirst}"
|
||||
Command="{Binding SortIncompletedSwitchCommand}">
|
||||
<AppBarToggleButton.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</AppBarToggleButton.Icon>
|
||||
</AppBarToggleButton>
|
||||
Command="{Binding SortIncompletedSwitchCommand}"/>
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -1,14 +1,70 @@
|
||||
<control:ScopedPage
|
||||
<shc:ScopedPage
|
||||
x:Class="Snap.Hutao.View.Page.GachaLogPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:control="using:Snap.Hutao.Control"
|
||||
xmlns:shc="using:Snap.Hutao.Control"
|
||||
xmlns:shv="using:Snap.Hutao.ViewModel"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance shv:GachaLogViewModel}"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<CommandBar DefaultLabelPosition="Right">
|
||||
<CommandBar.Background>
|
||||
<SolidColorBrush Color="{ThemeResource CardBackgroundFillColorSecondary}"/>
|
||||
</CommandBar.Background>
|
||||
<CommandBar.Content>
|
||||
<ComboBox
|
||||
MinWidth="120"
|
||||
Height="36"
|
||||
Margin="2,6,3,6"/>
|
||||
</CommandBar.Content>
|
||||
<AppBarButton Label="刷新" Icon="{shcm:FontIcon Glyph=}">
|
||||
<AppBarButton.Flyout>
|
||||
<MenuFlyout Placement="Bottom">
|
||||
<MenuFlyoutItem
|
||||
Text="从缓存刷新"
|
||||
Icon="{shcm:FontIcon Glyph=}"
|
||||
Command="{Binding RefreshByWebCacheCommand}"/>
|
||||
<MenuFlyoutItem
|
||||
Text="手动输入Url"
|
||||
Icon="{shcm:FontIcon Glyph=}"
|
||||
Command="{Binding RefreshByManualInputCommand}"/>
|
||||
</MenuFlyout>
|
||||
</AppBarButton.Flyout>
|
||||
</AppBarButton>
|
||||
<AppBarSeparator/>
|
||||
<AppBarButton Label="导入" Icon="{shcm:FontIcon Glyph=}">
|
||||
<AppBarButton.Flyout>
|
||||
<MenuFlyout Placement="Bottom">
|
||||
<MenuFlyoutItem
|
||||
Text="从 UIGF Json 文件导入"
|
||||
Command="{Binding ImportFromUIGFJsonCommand}"/>
|
||||
<MenuFlyoutItem
|
||||
Text="从 UIGF Excel 文件导入"
|
||||
Command="{Binding ImportFromUIGFExcelCommand}"/>
|
||||
</MenuFlyout>
|
||||
</AppBarButton.Flyout>
|
||||
</AppBarButton>
|
||||
<AppBarButton Label="导出" Icon="{shcm:FontIcon Glyph=}">
|
||||
<AppBarButton.Flyout>
|
||||
<MenuFlyout Placement="Bottom">
|
||||
<MenuFlyoutItem
|
||||
Text="导出到 UIGF Json 文件"
|
||||
Command="{Binding ExportToUIGFJsonCommand}"/>
|
||||
<MenuFlyoutItem
|
||||
Text="导出到 UIGF Excel 文件"
|
||||
Command="{Binding ExportToUIGFExcelCommand}"/>
|
||||
</MenuFlyout>
|
||||
</AppBarButton.Flyout>
|
||||
</AppBarButton>
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
</control:ScopedPage>
|
||||
</shc:ScopedPage>
|
||||
|
||||
@@ -269,7 +269,6 @@ internal class AchievementViewModel
|
||||
AchievementGoals = goals.OrderBy(goal => goal.Order).ToList();
|
||||
|
||||
Archives = achievementService.GetArchiveCollection();
|
||||
|
||||
SelectedArchive = Archives.SingleOrDefault(a => a.IsSelected == true);
|
||||
|
||||
if (SelectedArchive == null)
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.Factory.Abstraction;
|
||||
using Snap.Hutao.Model.Binding;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Service;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Service.GachaLog;
|
||||
using Snap.Hutao.Service.Metadata;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
@@ -9,8 +18,136 @@ namespace Snap.Hutao.ViewModel;
|
||||
/// 祈愿记录视图模型
|
||||
/// </summary>
|
||||
[Injection(InjectAs.Transient)]
|
||||
internal class GachaLogViewModel : ISupportCancellation
|
||||
internal class GachaLogViewModel : ObservableObject, ISupportCancellation
|
||||
{
|
||||
private readonly IMetadataService metadataService;
|
||||
private readonly IGachaLogService gachaLogService;
|
||||
private readonly IInfoBarService infoBarService;
|
||||
|
||||
private ObservableCollection<GachaArchive>? archives;
|
||||
private GachaArchive? selectedArchive;
|
||||
private GachaStatistics? statistics;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的祈愿记录视图模型
|
||||
/// </summary>
|
||||
/// <param name="metadataService">元数据服务</param>
|
||||
/// <param name="gachaLogService">祈愿记录服务</param>
|
||||
/// <param name="infoBarService">信息</param>
|
||||
/// <param name="asyncRelayCommandFactory">异步命令工厂</param>
|
||||
public GachaLogViewModel(
|
||||
IMetadataService metadataService,
|
||||
IGachaLogService gachaLogService,
|
||||
IInfoBarService infoBarService,
|
||||
IAsyncRelayCommandFactory asyncRelayCommandFactory)
|
||||
{
|
||||
this.metadataService = metadataService;
|
||||
this.gachaLogService = gachaLogService;
|
||||
this.infoBarService = infoBarService;
|
||||
|
||||
OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
|
||||
RefreshByWebCacheCommand = asyncRelayCommandFactory.Create(RefreshByWebCacheAsync);
|
||||
RefreshByManualInputCommand = asyncRelayCommandFactory.Create(RefreshByManualInputAsync);
|
||||
ImportFromUIGFExcelCommand = asyncRelayCommandFactory.Create(ImportFromUIGFExcelAsync);
|
||||
ImportFromUIGFJsonCommand = asyncRelayCommandFactory.Create(ImportFromUIGFJsonAsync);
|
||||
ExportToUIGFExcelCommand = asyncRelayCommandFactory.Create(ExportToUIGFExcelAsync);
|
||||
ExportToUIGFJsonCommand = asyncRelayCommandFactory.Create(ExportToUIGFJsonAsync);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CancellationToken CancellationToken { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 存档集合
|
||||
/// </summary>
|
||||
public ObservableCollection<GachaArchive>? Archives { get => archives; set => SetProperty(ref archives, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 选中的存档
|
||||
/// </summary>
|
||||
public GachaArchive? SelectedArchive { get => selectedArchive; set => SetProperty(ref selectedArchive, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 当前统计信息
|
||||
/// </summary>
|
||||
public GachaStatistics? Statistics { get => statistics; set => SetProperty(ref statistics, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 页面加载命令
|
||||
/// </summary>
|
||||
public ICommand OpenUICommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 浏览器缓存刷新命令
|
||||
/// </summary>
|
||||
public ICommand RefreshByWebCacheCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 手动输入Url刷新命令
|
||||
/// </summary>
|
||||
public ICommand RefreshByManualInputCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 从 UIGF Excel 导入命令
|
||||
/// </summary>
|
||||
public ICommand ImportFromUIGFExcelCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 从 UIGF Json 导入命令
|
||||
/// </summary>
|
||||
public ICommand ImportFromUIGFJsonCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 导出到 UIGF Excel 命令
|
||||
/// </summary>
|
||||
public ICommand ExportToUIGFExcelCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 导出到 UIGF Json 命令
|
||||
/// </summary>
|
||||
public ICommand ExportToUIGFJsonCommand { get; }
|
||||
|
||||
private async Task OpenUIAsync()
|
||||
{
|
||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||
{
|
||||
Archives = gachaLogService.GetArchiveCollection();
|
||||
SelectedArchive = Archives.SingleOrDefault(a => a.IsSelected == true);
|
||||
|
||||
if (SelectedArchive == null)
|
||||
{
|
||||
//infoBarService.Warning("请创建一个成就存档");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RefreshByWebCacheAsync()
|
||||
{
|
||||
Statistics = await gachaLogService.RefreshAsync();
|
||||
}
|
||||
|
||||
private async Task RefreshByManualInputAsync()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task ImportFromUIGFExcelAsync()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task ImportFromUIGFJsonAsync()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task ExportToUIGFExcelAsync()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task ExportToUIGFJsonAsync()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using MiniExcelLibs.Attributes;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
|
||||
@@ -13,12 +14,14 @@ public class GachaLogItem
|
||||
/// <summary>
|
||||
/// 玩家Uid
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "uid")]
|
||||
[JsonPropertyName("uid")]
|
||||
public string Uid { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 祈愿类型
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "gacha_type")]
|
||||
[JsonPropertyName("gacha_type")]
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public GachaConfigType GachaType { get; set; } = default!;
|
||||
@@ -26,14 +29,15 @@ public class GachaLogItem
|
||||
/// <summary>
|
||||
/// 总为 <see cref="string.Empty"/>
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "item_id")]
|
||||
[Obsolete("API clear this property")]
|
||||
[JsonPropertyName("item_id")]
|
||||
public string ItemId { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 个数
|
||||
/// 一般为 1
|
||||
/// 个数 一般为 1
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "count")]
|
||||
[JsonPropertyName("count")]
|
||||
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
|
||||
public int Count { get; set; }
|
||||
@@ -41,6 +45,7 @@ public class GachaLogItem
|
||||
/// <summary>
|
||||
/// 时间
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "time", Format = "yyyy-MM-dd HH:mm:ss")]
|
||||
[JsonPropertyName("time")]
|
||||
[JsonConverter(typeof(Core.Json.Converter.DateTimeOffsetConverter))]
|
||||
public DateTimeOffset Time { get; set; }
|
||||
@@ -48,24 +53,28 @@ public class GachaLogItem
|
||||
/// <summary>
|
||||
/// 物品名称
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "name")]
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 语言
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "lang")]
|
||||
[JsonPropertyName("lang")]
|
||||
public string Language { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 物品类型
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "item_type")]
|
||||
[JsonPropertyName("item_type")]
|
||||
public string ItemType { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 物品稀有等级
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "rank_type")]
|
||||
[JsonPropertyName("rank_type")]
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public ItemQuality Rank { get; set; } = default!;
|
||||
@@ -73,6 +82,7 @@ public class GachaLogItem
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
[ExcelColumn(Name = "id")]
|
||||
[JsonPropertyName("id")]
|
||||
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
|
||||
public long Id { get; set; } = default!;
|
||||
|
||||
@@ -19,8 +19,7 @@ internal static class MemoryExtensions
|
||||
public static unsafe string AsString(this MODULEENTRY32.__winmdroot_Foundation_CHAR_256 char256)
|
||||
{
|
||||
byte* pszModule = (byte*)&char256;
|
||||
string szModule = Encoding.UTF8.GetString(pszModule, StringLength(pszModule));
|
||||
return szModule;
|
||||
return Encoding.UTF8.GetString(pszModule, StringLength(pszModule));
|
||||
}
|
||||
|
||||
private static unsafe int StringLength(byte* pszStr)
|
||||
|
||||
@@ -13,7 +13,7 @@ internal static class StructMarshal
|
||||
/// <summary>
|
||||
/// 构造一个新的 <see cref="Windows.Win32.System.Diagnostics.ToolHelp.MODULEENTRY32"/>
|
||||
/// </summary>
|
||||
/// <returns>实例</returns>
|
||||
/// <returns>新的实例</returns>
|
||||
public static unsafe MODULEENTRY32 MODULEENTRY32()
|
||||
{
|
||||
return new() { dwSize = (uint)sizeof(MODULEENTRY32) };
|
||||
|
||||
Reference in New Issue
Block a user