mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
improve db layer & homecard experience
This commit is contained in:
@@ -1,55 +0,0 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
|
||||||
using CommunityToolkit.WinUI.Behaviors;
|
|
||||||
using Microsoft.UI.Xaml.Controls;
|
|
||||||
|
|
||||||
namespace Snap.Hutao.Control.Behavior;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// AppTitleBar Workaround
|
|
||||||
/// https://github.com/microsoft/microsoft-ui-xaml/issues/7756
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class ComboBoxExtendsContentIntoTitleBarWorkaroundBehavior : BehaviorBase<ComboBox>
|
|
||||||
{
|
|
||||||
private readonly IMessenger messenger;
|
|
||||||
private readonly EventHandler<object> dropDownOpenedHandler;
|
|
||||||
private readonly EventHandler<object> dropDownClosedHandler;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// AppTitleBar Workaround
|
|
||||||
/// </summary>
|
|
||||||
public ComboBoxExtendsContentIntoTitleBarWorkaroundBehavior()
|
|
||||||
{
|
|
||||||
messenger = Ioc.Default.GetRequiredService<IMessenger>();
|
|
||||||
dropDownOpenedHandler = OnDropDownOpened;
|
|
||||||
dropDownClosedHandler = OnDropDownClosed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
protected override bool Initialize()
|
|
||||||
{
|
|
||||||
AssociatedObject.DropDownOpened += dropDownOpenedHandler;
|
|
||||||
AssociatedObject.DropDownClosed += dropDownClosedHandler;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
protected override bool Uninitialize()
|
|
||||||
{
|
|
||||||
AssociatedObject.DropDownOpened -= dropDownOpenedHandler;
|
|
||||||
AssociatedObject.DropDownClosed -= dropDownClosedHandler;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDropDownOpened(object? sender, object e)
|
|
||||||
{
|
|
||||||
messenger.Send(Message.FlyoutStateChangedMessage.Open);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDropDownClosed(object? sender, object e)
|
|
||||||
{
|
|
||||||
messenger.Send(Message.FlyoutStateChangedMessage.Close);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,23 @@
|
|||||||
// 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 CommunityToolkit.WinUI.Notifications;
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.Windows.AppLifecycle;
|
|
||||||
using Snap.Hutao.Core.Setting;
|
|
||||||
using Snap.Hutao.Service.DailyNote;
|
|
||||||
using Snap.Hutao.Service.Hutao;
|
|
||||||
using Snap.Hutao.Service.Metadata;
|
|
||||||
using Snap.Hutao.Service.Navigation;
|
|
||||||
using Snap.Hutao.ViewModel.Guide;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Snap.Hutao.Core.LifeCycle;
|
namespace Snap.Hutao.Core.LifeCycle;
|
||||||
|
|
||||||
[Injection(InjectAs.Singleton, typeof(ICurrentWindowReference))]
|
[Injection(InjectAs.Singleton, typeof(ICurrentWindowReference))]
|
||||||
internal sealed class CurrentWindowReference : ICurrentWindowReference
|
internal sealed class CurrentWindowReference : ICurrentWindowReference
|
||||||
{
|
{
|
||||||
public Window Window { get; set; } = default!;
|
private readonly WeakReference<Window> reference = new(default!);
|
||||||
|
|
||||||
|
[SuppressMessage("", "SH007")]
|
||||||
|
public Window Window
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
reference.TryGetTarget(out Window? window);
|
||||||
|
return window!;
|
||||||
|
}
|
||||||
|
set => reference.SetTarget(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
|
|
||||||
namespace Snap.Hutao.Core.Setting;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 功能
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class Feature : ObservableObject
|
|
||||||
{
|
|
||||||
private readonly string displayName;
|
|
||||||
private readonly string description;
|
|
||||||
private readonly string settingKey;
|
|
||||||
private readonly bool defaultValue;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造一个新的功能
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="displayName">显示名称</param>
|
|
||||||
/// <param name="description">描述</param>
|
|
||||||
/// <param name="settingKey">键</param>
|
|
||||||
/// <param name="defaultValue">默认值</param>
|
|
||||||
public Feature(string displayName, string description, string settingKey, bool defaultValue)
|
|
||||||
{
|
|
||||||
this.displayName = displayName;
|
|
||||||
this.description = description;
|
|
||||||
this.settingKey = settingKey;
|
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 显示名称
|
|
||||||
/// </summary>
|
|
||||||
public string DisplayName { get => displayName; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 描述
|
|
||||||
/// </summary>
|
|
||||||
public string Description { get => description; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 值
|
|
||||||
/// </summary>
|
|
||||||
public bool Value
|
|
||||||
{
|
|
||||||
get => LocalSetting.Get(settingKey, defaultValue);
|
|
||||||
set
|
|
||||||
{
|
|
||||||
LocalSetting.Set(settingKey, value);
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
|
|
||||||
using System.Collections;
|
|
||||||
|
|
||||||
namespace Snap.Hutao.Core.Setting;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 功能选项
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class FeatureOptions : IReadOnlyCollection<Feature>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 启用实时便笺无感验证
|
|
||||||
/// </summary>
|
|
||||||
public Feature IsDailyNoteSilentVerificationEnabled { get; } = new(
|
|
||||||
"IsDailyNoteSilentVerificationEnabled", "启用实时便笺无感验证", "IsDailyNoteSilentVerificationEnabled", true);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 元数据检查是否忽略
|
|
||||||
/// </summary>
|
|
||||||
public Feature IsMetadataUpdateCheckSuppressed { get; } = new(
|
|
||||||
"IsMetadataUpdateCheckSuppressed", "禁用元数据更新检查", "IsMetadataUpdateCheckSuppressed", false);
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public int Count { get => 2; }
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public IEnumerator<Feature> GetEnumerator()
|
|
||||||
{
|
|
||||||
// TODO: Use source generator
|
|
||||||
yield return IsDailyNoteSilentVerificationEnabled;
|
|
||||||
yield return IsMetadataUpdateCheckSuppressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
|
||||||
{
|
|
||||||
return GetEnumerator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -76,4 +76,9 @@ internal static class SettingKeys
|
|||||||
public const string CultivationWeapon90LevelTarget = "CultivationWeapon90LevelTarget";
|
public const string CultivationWeapon90LevelTarget = "CultivationWeapon90LevelTarget";
|
||||||
public const string CultivationWeapon70LevelCurrent = "CultivationWeapon70LevelCurrent";
|
public const string CultivationWeapon70LevelCurrent = "CultivationWeapon70LevelCurrent";
|
||||||
public const string CultivationWeapon70LevelTarget = "CultivationWeapon70LevelTarget";
|
public const string CultivationWeapon70LevelTarget = "CultivationWeapon70LevelTarget";
|
||||||
|
|
||||||
|
public const string IsHomeCardLaunchGamePresented = "IsHomeCardLaunchGamePresented";
|
||||||
|
public const string IsHomeCardGachaStatisticsPresented = "IsHomeCardGachaStatisticsPresented";
|
||||||
|
public const string IsHomeCardAchievementPresented = "IsHomeCardAchievementPresented";
|
||||||
|
public const string IsHomeCardDailyNotePresented = "IsHomeCardDailyNotePresented";
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,10 @@ internal sealed partial class ShellLinkInterop : IShellLinkInterop
|
|||||||
|
|
||||||
public void CreateDesktopShoutcutForElevatedLaunch()
|
public void CreateDesktopShoutcutForElevatedLaunch()
|
||||||
{
|
{
|
||||||
|
string sourceLogoPath = Path.Combine(runtimeOptions.InstalledLocation, "Assets/Logo.ico");
|
||||||
|
string targetLogoPath = Path.Combine(runtimeOptions.DataFolder, "ShellLinkLogo.ico");
|
||||||
|
File.Copy(sourceLogoPath, targetLogoPath);
|
||||||
|
|
||||||
IShellLinkW shellLink = (IShellLinkW)new ShellLink();
|
IShellLinkW shellLink = (IShellLinkW)new ShellLink();
|
||||||
shellLink.SetPath("powershell");
|
shellLink.SetPath("powershell");
|
||||||
shellLink.SetArguments($"""
|
shellLink.SetArguments($"""
|
||||||
@@ -24,8 +28,7 @@ internal sealed partial class ShellLinkInterop : IShellLinkInterop
|
|||||||
""");
|
""");
|
||||||
shellLink.SetShowCmd(SHOW_WINDOW_CMD.SW_SHOWMINNOACTIVE);
|
shellLink.SetShowCmd(SHOW_WINDOW_CMD.SW_SHOWMINNOACTIVE);
|
||||||
|
|
||||||
string iconPath = Path.Combine(runtimeOptions.InstalledLocation, "Snap.Hutao.exe");
|
shellLink.SetIconLocation(targetLogoPath, 0);
|
||||||
shellLink.SetIconLocation(iconPath, 0);
|
|
||||||
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||||
string target = Path.Combine(desktop, $"{SH.AppNameAndVersion.Format(runtimeOptions.Version)}.lnk");
|
string target = Path.Combine(desktop, $"{SH.AppNameAndVersion.Format(runtimeOptions.Version)}.lnk");
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ internal sealed class CalculableWeapon
|
|||||||
IMappingFrom<CalculableWeapon, Weapon>,
|
IMappingFrom<CalculableWeapon, Weapon>,
|
||||||
IMappingFrom<CalculableWeapon, WeaponView>
|
IMappingFrom<CalculableWeapon, WeaponView>
|
||||||
{
|
{
|
||||||
private uint levelCurrent;
|
|
||||||
private uint levelTarget;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个新的可计算武器
|
/// 构造一个新的可计算武器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -13,32 +13,8 @@ internal sealed class UIIFItem
|
|||||||
/// 物品Id
|
/// 物品Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonPropertyName("itemId")]
|
[JsonPropertyName("itemId")]
|
||||||
public int ItemId { get; set; }
|
public uint ItemId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
[JsonPropertyName("material")]
|
||||||
/// 物品Id
|
public UIIFMaterial Material { get; set; } = default!;
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("count")]
|
|
||||||
public int Count { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 等级
|
|
||||||
/// Reliquary/Weapon
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("level")]
|
|
||||||
public int? Level { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 副属性列表
|
|
||||||
/// Reliquary
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("appendPropIdList")]
|
|
||||||
public List<int>? AppendPropIdList { get; set; } = default!;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 精炼等级 0-4
|
|
||||||
/// Weapon
|
|
||||||
/// </summary>
|
|
||||||
[JsonPropertyName("promoteLevel")]
|
|
||||||
public int? PromoteLevel { get; set; }
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Model.InterChange.Inventory;
|
||||||
|
|
||||||
|
internal sealed class UIIFMaterial
|
||||||
|
{
|
||||||
|
public uint Count { get; set; }
|
||||||
|
}
|
||||||
BIN
src/Snap.Hutao/Snap.Hutao/Resource/BlurBackground.png
Normal file
BIN
src/Snap.Hutao/Snap.Hutao/Resource/BlurBackground.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 158 KiB |
@@ -5245,7 +5245,7 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 在桌面上创建默认以管理员方式启动的快捷方式,更新后需要重新创建 的本地化字符串。
|
/// 查找类似 在桌面上创建默认以管理员方式启动的快捷方式 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string ViewPageSettingCreateDesktopShortcutDescription {
|
internal static string ViewPageSettingCreateDesktopShortcutDescription {
|
||||||
get {
|
get {
|
||||||
@@ -5469,6 +5469,87 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 管理主页仪表板中的卡片 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewpageSettingHomeCardDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewpageSettingHomeCardDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 主页卡片 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewpageSettingHomeCardHeader {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewpageSettingHomeCardHeader", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 成就管理 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewpageSettingHomeCardItemAchievementHeader {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewpageSettingHomeCardItemAchievementHeader", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 实时便笺 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewpageSettingHomeCardItemDailyNoteHeader {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewpageSettingHomeCardItemDailyNoteHeader", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 祈愿记录 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewpageSettingHomeCardItemgachaStatisticsHeader {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewpageSettingHomeCardItemgachaStatisticsHeader", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 启动游戏 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewpageSettingHomeCardItemLaunchGameHeader {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewpageSettingHomeCardItemLaunchGameHeader", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 隐藏 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewPageSettingHomeCardOff {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewPageSettingHomeCardOff", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 显示 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewPageSettingHomeCardOn {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewPageSettingHomeCardOn", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 主页 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewpageSettingHomeHeader {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewpageSettingHomeHeader", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 胡桃账号 的本地化字符串。
|
/// 查找类似 胡桃账号 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -5577,6 +5658,15 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 胡桃使用 PowerShell 更改注册表中的信息以修改游戏内账号 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewPageSettingSetPowerShellDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewPageSettingSetPowerShellDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 PowerShell 路径 的本地化字符串。
|
/// 查找类似 PowerShell 路径 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -5586,6 +5676,15 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Shell 体验 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewPageSettingShellExperienceHeader {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewPageSettingShellExperienceHeader", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 赞助我们 的本地化字符串。
|
/// 查找类似 赞助我们 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1902,7 +1902,7 @@
|
|||||||
<value>创建</value>
|
<value>创建</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ViewPageSettingCreateDesktopShortcutDescription" xml:space="preserve">
|
<data name="ViewPageSettingCreateDesktopShortcutDescription" xml:space="preserve">
|
||||||
<value>在桌面上创建默认以管理员方式启动的快捷方式,更新后需要重新创建</value>
|
<value>在桌面上创建默认以管理员方式启动的快捷方式</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ViewPageSettingCreateDesktopShortcutHeader" xml:space="preserve">
|
<data name="ViewPageSettingCreateDesktopShortcutHeader" xml:space="preserve">
|
||||||
<value>创建快捷方式</value>
|
<value>创建快捷方式</value>
|
||||||
@@ -1976,6 +1976,33 @@
|
|||||||
<data name="ViewPageSettingGeetestVerificationHeader" xml:space="preserve">
|
<data name="ViewPageSettingGeetestVerificationHeader" xml:space="preserve">
|
||||||
<value>无感验证</value>
|
<value>无感验证</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewpageSettingHomeCardDescription" xml:space="preserve">
|
||||||
|
<value>管理主页仪表板中的卡片</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewpageSettingHomeCardHeader" xml:space="preserve">
|
||||||
|
<value>主页卡片</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewpageSettingHomeCardItemAchievementHeader" xml:space="preserve">
|
||||||
|
<value>成就管理</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewpageSettingHomeCardItemDailyNoteHeader" xml:space="preserve">
|
||||||
|
<value>实时便笺</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewpageSettingHomeCardItemgachaStatisticsHeader" xml:space="preserve">
|
||||||
|
<value>祈愿记录</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewpageSettingHomeCardItemLaunchGameHeader" xml:space="preserve">
|
||||||
|
<value>启动游戏</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewPageSettingHomeCardOff" xml:space="preserve">
|
||||||
|
<value>隐藏</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewPageSettingHomeCardOn" xml:space="preserve">
|
||||||
|
<value>显示</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewpageSettingHomeHeader" xml:space="preserve">
|
||||||
|
<value>主页</value>
|
||||||
|
</data>
|
||||||
<data name="ViewPageSettingHutaoPassportHeader" xml:space="preserve">
|
<data name="ViewPageSettingHutaoPassportHeader" xml:space="preserve">
|
||||||
<value>胡桃账号</value>
|
<value>胡桃账号</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2012,9 +2039,15 @@
|
|||||||
<data name="ViewPageSettingSetGamePathHint" xml:space="preserve">
|
<data name="ViewPageSettingSetGamePathHint" xml:space="preserve">
|
||||||
<value>设置游戏路径时,请选择游戏本体(YuanShen.exe 或 GenshinImpact.exe)而不是启动器(launcher.exe)</value>
|
<value>设置游戏路径时,请选择游戏本体(YuanShen.exe 或 GenshinImpact.exe)而不是启动器(launcher.exe)</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewPageSettingSetPowerShellDescription" xml:space="preserve">
|
||||||
|
<value>胡桃使用 PowerShell 更改注册表中的信息以修改游戏内账号</value>
|
||||||
|
</data>
|
||||||
<data name="ViewPageSettingSetPowerShellPathHeader" xml:space="preserve">
|
<data name="ViewPageSettingSetPowerShellPathHeader" xml:space="preserve">
|
||||||
<value>PowerShell 路径</value>
|
<value>PowerShell 路径</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewPageSettingShellExperienceHeader" xml:space="preserve">
|
||||||
|
<value>Shell 体验</value>
|
||||||
|
</data>
|
||||||
<data name="ViewPageSettingSponsorNavigate" xml:space="preserve">
|
<data name="ViewPageSettingSponsorNavigate" xml:space="preserve">
|
||||||
<value>赞助我们</value>
|
<value>赞助我们</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -89,6 +89,21 @@ internal sealed partial class AchievementDbService : IAchievementDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask OverwriteAchievementAsync(EntityAchievement achievement)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
|
||||||
|
// Delete exists one.
|
||||||
|
await appDbContext.Achievements.ExecuteDeleteWhereAsync(e => e.InnerId == achievement.InnerId).ConfigureAwait(false);
|
||||||
|
if (achievement.Status >= Model.Intrinsic.AchievementStatus.STATUS_FINISHED)
|
||||||
|
{
|
||||||
|
await appDbContext.Achievements.AddAndSaveAsync(achievement).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ObservableCollection<AchievementArchive> GetAchievementArchiveCollection()
|
public ObservableCollection<AchievementArchive> GetAchievementArchiveCollection()
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -98,7 +113,7 @@ internal sealed partial class AchievementDbService : IAchievementDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask DeleteAchievementArchiveAsync(AchievementArchive archive)
|
public async ValueTask RemoveAchievementArchiveAsync(AchievementArchive archive)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -121,6 +136,19 @@ internal sealed partial class AchievementDbService : IAchievementDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask<List<EntityAchievement>> GetAchievementListByArchiveIdAsync(Guid archiveId)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
return await appDbContext.Achievements
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(i => i.ArchiveId == archiveId)
|
||||||
|
.ToListAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<AchievementArchive> GetAchievementArchiveList()
|
public List<AchievementArchive> GetAchievementArchiveList()
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -129,4 +157,13 @@ internal sealed partial class AchievementDbService : IAchievementDbService
|
|||||||
return appDbContext.AchievementArchives.AsNoTracking().ToList();
|
return appDbContext.AchievementArchives.AsNoTracking().ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask<List<AchievementArchive>> GetAchievementArchiveListAsync()
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
return await appDbContext.AchievementArchives.AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -74,6 +74,6 @@ internal sealed partial class AchievementService
|
|||||||
|
|
||||||
// Sync database
|
// Sync database
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
await achievementDbService.DeleteAchievementArchiveAsync(archive).ConfigureAwait(false);
|
await achievementDbService.RemoveAchievementArchiveAsync(archive).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,9 +50,10 @@ internal sealed partial class AchievementService
|
|||||||
public async ValueTask<UIAF> ExportToUIAFAsync(AchievementArchive archive)
|
public async ValueTask<UIAF> ExportToUIAFAsync(AchievementArchive archive)
|
||||||
{
|
{
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
List<UIAFItem> list = achievementDbService
|
List<EntityAchievement> entities = await achievementDbService
|
||||||
.GetAchievementListByArchiveId(archive.InnerId)
|
.GetAchievementListByArchiveIdAsync(archive.InnerId)
|
||||||
.SelectList(UIAFItem.From);
|
.ConfigureAwait(false);
|
||||||
|
List<UIAFItem> list = entities.SelectList(UIAFItem.From);
|
||||||
|
|
||||||
return new()
|
return new()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ internal sealed partial class AchievementStatisticsService : IAchievementStatist
|
|||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
|
|
||||||
List<AchievementStatistics> results = new();
|
List<AchievementStatistics> results = new();
|
||||||
foreach (AchievementArchive archive in achievementDbService.GetAchievementArchiveList())
|
foreach (AchievementArchive archive in await achievementDbService.GetAchievementArchiveListAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
int finishedCount = await achievementDbService
|
int finishedCount = await achievementDbService
|
||||||
.GetFinishedAchievementCountByArchiveIdAsync(archive.InnerId)
|
.GetFinishedAchievementCountByArchiveIdAsync(archive.InnerId)
|
||||||
|
|||||||
@@ -9,14 +9,18 @@ namespace Snap.Hutao.Service.Achievement;
|
|||||||
|
|
||||||
internal interface IAchievementDbService
|
internal interface IAchievementDbService
|
||||||
{
|
{
|
||||||
ValueTask DeleteAchievementArchiveAsync(Model.Entity.AchievementArchive archive);
|
ValueTask RemoveAchievementArchiveAsync(Model.Entity.AchievementArchive archive);
|
||||||
|
|
||||||
ObservableCollection<Model.Entity.AchievementArchive> GetAchievementArchiveCollection();
|
ObservableCollection<Model.Entity.AchievementArchive> GetAchievementArchiveCollection();
|
||||||
|
|
||||||
List<Model.Entity.AchievementArchive> GetAchievementArchiveList();
|
List<Model.Entity.AchievementArchive> GetAchievementArchiveList();
|
||||||
|
|
||||||
|
ValueTask<List<Model.Entity.AchievementArchive>> GetAchievementArchiveListAsync();
|
||||||
|
|
||||||
List<EntityAchievement> GetAchievementListByArchiveId(Guid archiveId);
|
List<EntityAchievement> GetAchievementListByArchiveId(Guid archiveId);
|
||||||
|
|
||||||
|
ValueTask<List<EntityAchievement>> GetAchievementListByArchiveIdAsync(Guid archiveId);
|
||||||
|
|
||||||
Dictionary<AchievementId, EntityAchievement> GetAchievementMapByArchiveId(Guid archiveId);
|
Dictionary<AchievementId, EntityAchievement> GetAchievementMapByArchiveId(Guid archiveId);
|
||||||
|
|
||||||
ValueTask<int> GetFinishedAchievementCountByArchiveIdAsync(Guid archiveId);
|
ValueTask<int> GetFinishedAchievementCountByArchiveIdAsync(Guid archiveId);
|
||||||
@@ -24,4 +28,6 @@ internal interface IAchievementDbService
|
|||||||
ValueTask<List<EntityAchievement>> GetLatestFinishedAchievementListByArchiveIdAsync(Guid archiveId, int take);
|
ValueTask<List<EntityAchievement>> GetLatestFinishedAchievementListByArchiveIdAsync(Guid archiveId, int take);
|
||||||
|
|
||||||
void OverwriteAchievement(EntityAchievement achievement);
|
void OverwriteAchievement(EntityAchievement achievement);
|
||||||
|
|
||||||
|
ValueTask OverwriteAchievementAsync(EntityAchievement achievement);
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
{
|
{
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
string uid = userAndUid.Uid.Value;
|
string uid = userAndUid.Uid.Value;
|
||||||
List<EntityAvatarInfo> dbInfos = avatarInfoDbService.GetAvatarInfoListByUid(uid);
|
List<EntityAvatarInfo> dbInfos = await avatarInfoDbService.GetAvatarInfoListByUidAsync(uid).ConfigureAwait(false);
|
||||||
EnsureItemsAvatarIdDistinct(ref dbInfos, uid);
|
EnsureItemsAvatarIdDistinct(ref dbInfos, uid);
|
||||||
|
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -121,7 +121,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return avatarInfoDbService.GetAvatarInfoListByUid(uid);
|
return await avatarInfoDbService.GetAvatarInfoListByUidAsync(uid).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -134,7 +134,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
{
|
{
|
||||||
token.ThrowIfCancellationRequested();
|
token.ThrowIfCancellationRequested();
|
||||||
string uid = userAndUid.Uid.Value;
|
string uid = userAndUid.Uid.Value;
|
||||||
List<EntityAvatarInfo> dbInfos = avatarInfoDbService.GetAvatarInfoListByUid(uid);
|
List<EntityAvatarInfo> dbInfos = await avatarInfoDbService.GetAvatarInfoListByUidAsync(uid).ConfigureAwait(false);
|
||||||
EnsureItemsAvatarIdDistinct(ref dbInfos, uid);
|
EnsureItemsAvatarIdDistinct(ref dbInfos, uid);
|
||||||
|
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -173,7 +173,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return avatarInfoDbService.GetAvatarInfoListByUid(uid);
|
return await avatarInfoDbService.GetAvatarInfoListByUidAsync(uid).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -243,7 +243,7 @@ internal sealed partial class AvatarInfoDbBulkOperation
|
|||||||
// This means that there are duplicate items.
|
// This means that there are duplicate items.
|
||||||
if (distinctCount < dbInfos.Count)
|
if (distinctCount < dbInfos.Count)
|
||||||
{
|
{
|
||||||
avatarInfoDbService.DeleteAvatarInfoRangeByUid(uid);
|
avatarInfoDbService.RemoveAvatarInfoRangeByUid(uid);
|
||||||
dbInfos = new();
|
dbInfos = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,20 @@ internal sealed partial class AvatarInfoDbService : IAvatarInfoDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteAvatarInfoRangeByUid(string uid)
|
public async ValueTask<List<EntityAvatarInfo>> GetAvatarInfoListByUidAsync(string uid)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
return await appDbContext.AvatarInfos
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(i => i.Uid == uid)
|
||||||
|
.ToListAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAvatarInfoRangeByUid(string uid)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -32,4 +45,13 @@ internal sealed partial class AvatarInfoDbService : IAvatarInfoDbService
|
|||||||
appDbContext.AvatarInfos.ExecuteDeleteWhere(i => i.Uid == uid);
|
appDbContext.AvatarInfos.ExecuteDeleteWhere(i => i.Uid == uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask RemoveAvatarInfoRangeByUidAsync(string uid)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.AvatarInfos.ExecuteDeleteWhereAsync(i => i.Uid == uid).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ internal sealed partial class AvatarInfoService : IAvatarInfoService
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
List<EntityAvatarInfo> list = avatarInfoDbService.GetAvatarInfoListByUid(userAndUid.Uid.Value);
|
List<EntityAvatarInfo> list = await avatarInfoDbService.GetAvatarInfoListByUidAsync(userAndUid.Uid.Value).ConfigureAwait(false);
|
||||||
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);
|
||||||
@@ -97,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<Model.Entity.AvatarInfo> avatarInfos, CancellationToken token)
|
private async ValueTask<Summary> GetSummaryCoreAsync(IEnumerable<EntityAvatarInfo> avatarInfos, CancellationToken token)
|
||||||
{
|
{
|
||||||
using (ValueStopwatch.MeasureExecution(logger))
|
using (ValueStopwatch.MeasureExecution(logger))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ namespace Snap.Hutao.Service.AvatarInfo;
|
|||||||
|
|
||||||
internal interface IAvatarInfoDbService
|
internal interface IAvatarInfoDbService
|
||||||
{
|
{
|
||||||
void DeleteAvatarInfoRangeByUid(string uid);
|
void RemoveAvatarInfoRangeByUid(string uid);
|
||||||
|
|
||||||
List<EntityAvatarInfo> GetAvatarInfoListByUid(string uid);
|
List<EntityAvatarInfo> GetAvatarInfoListByUid(string uid);
|
||||||
|
|
||||||
|
ValueTask<List<EntityAvatarInfo>> GetAvatarInfoListByUidAsync(string uid);
|
||||||
|
|
||||||
|
ValueTask RemoveAvatarInfoRangeByUidAsync(string uid);
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ internal sealed partial class CultivationDbService : ICultivationDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask DeleteCultivateEntryByIdAsync(Guid entryId)
|
public async ValueTask RemoveCultivateEntryByIdAsync(Guid entryId)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -77,15 +77,6 @@ internal sealed partial class CultivationDbService : ICultivationDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateInventoryItem(InventoryItem item)
|
|
||||||
{
|
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
|
||||||
{
|
|
||||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
|
||||||
appDbContext.InventoryItems.UpdateAndSave(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateCultivateItem(CultivateItem item)
|
public void UpdateCultivateItem(CultivateItem item)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -95,6 +86,15 @@ internal sealed partial class CultivationDbService : ICultivationDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask UpdateCultivateItemAsync(CultivateItem item)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.CultivateItems.UpdateAndSaveAsync(item).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async ValueTask<CultivateEntry?> GetCultivateEntryByProjectIdAndItemIdAsync(Guid projectId, uint itemId)
|
public async ValueTask<CultivateEntry?> GetCultivateEntryByProjectIdAndItemIdAsync(Guid projectId, uint itemId)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -115,7 +115,7 @@ internal sealed partial class CultivationDbService : ICultivationDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask DeleteCultivateItemRangeByEntryIdAsync(Guid entryId)
|
public async ValueTask RemoveCultivateItemRangeByEntryIdAsync(Guid entryId)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -144,7 +144,7 @@ internal sealed partial class CultivationDbService : ICultivationDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask DeleteCultivateProjectByIdAsync(Guid projectId)
|
public async ValueTask RemoveCultivateProjectByIdAsync(Guid projectId)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,6 +75,6 @@ internal sealed partial class CultivationService
|
|||||||
|
|
||||||
// Sync database
|
// Sync database
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
await cultivationDbService.DeleteCultivateProjectByIdAsync(project.InnerId).ConfigureAwait(false);
|
await cultivationDbService.RemoveCultivateProjectByIdAsync(project.InnerId).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Snap.Hutao.Model.Entity.Database;
|
|||||||
using Snap.Hutao.Model.Entity.Primitive;
|
using Snap.Hutao.Model.Entity.Primitive;
|
||||||
using Snap.Hutao.Model.Metadata.Item;
|
using Snap.Hutao.Model.Metadata.Item;
|
||||||
using Snap.Hutao.Model.Primitive;
|
using Snap.Hutao.Model.Primitive;
|
||||||
|
using Snap.Hutao.Service.Inventroy;
|
||||||
using Snap.Hutao.ViewModel.Cultivation;
|
using Snap.Hutao.ViewModel.Cultivation;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ internal sealed partial class CultivationService : ICultivationService
|
|||||||
{
|
{
|
||||||
private readonly ScopedDbCurrent<CultivateProject, Message.CultivateProjectChangedMessage> dbCurrent;
|
private readonly ScopedDbCurrent<CultivateProject, Message.CultivateProjectChangedMessage> dbCurrent;
|
||||||
private readonly ICultivationDbService cultivationDbService;
|
private readonly ICultivationDbService cultivationDbService;
|
||||||
|
private readonly IInventoryDbService inventoryDbService;
|
||||||
private readonly IServiceProvider serviceProvider;
|
private readonly IServiceProvider serviceProvider;
|
||||||
private readonly ITaskContext taskContext;
|
private readonly ITaskContext taskContext;
|
||||||
|
|
||||||
@@ -140,13 +142,13 @@ internal sealed partial class CultivationService : ICultivationService
|
|||||||
public async ValueTask RemoveCultivateEntryAsync(Guid entryId)
|
public async ValueTask RemoveCultivateEntryAsync(Guid entryId)
|
||||||
{
|
{
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
await cultivationDbService.DeleteCultivateEntryByIdAsync(entryId).ConfigureAwait(false);
|
await cultivationDbService.RemoveCultivateEntryByIdAsync(entryId).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void SaveInventoryItem(InventoryItemView item)
|
public void SaveInventoryItem(InventoryItemView item)
|
||||||
{
|
{
|
||||||
cultivationDbService.UpdateInventoryItem(item.Entity);
|
inventoryDbService.UpdateInventoryItem(item.Entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -181,7 +183,7 @@ internal sealed partial class CultivationService : ICultivationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
Guid entryId = entry.InnerId;
|
Guid entryId = entry.InnerId;
|
||||||
await cultivationDbService.DeleteCultivateItemRangeByEntryIdAsync(entryId).ConfigureAwait(false);
|
await cultivationDbService.RemoveCultivateItemRangeByEntryIdAsync(entryId).ConfigureAwait(false);
|
||||||
|
|
||||||
IEnumerable<CultivateItem> toAdd = items.Select(item => CultivateItem.From(entryId, item));
|
IEnumerable<CultivateItem> toAdd = items.Select(item => CultivateItem.From(entryId, item));
|
||||||
await cultivationDbService.AddCultivateItemRangeAsync(toAdd).ConfigureAwait(false);
|
await cultivationDbService.AddCultivateItemRangeAsync(toAdd).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ internal interface ICultivationDbService
|
|||||||
{
|
{
|
||||||
ValueTask AddCultivateProjectAsync(CultivateProject project);
|
ValueTask AddCultivateProjectAsync(CultivateProject project);
|
||||||
|
|
||||||
ValueTask DeleteCultivateEntryByIdAsync(Guid entryId);
|
ValueTask RemoveCultivateEntryByIdAsync(Guid entryId);
|
||||||
|
|
||||||
ValueTask DeleteCultivateItemRangeByEntryIdAsync(Guid entryId);
|
ValueTask RemoveCultivateItemRangeByEntryIdAsync(Guid entryId);
|
||||||
|
|
||||||
ValueTask DeleteCultivateProjectByIdAsync(Guid projectId);
|
ValueTask RemoveCultivateProjectByIdAsync(Guid projectId);
|
||||||
|
|
||||||
ValueTask<CultivateEntry?> GetCultivateEntryByProjectIdAndItemIdAsync(Guid projectId, uint itemId);
|
ValueTask<CultivateEntry?> GetCultivateEntryByProjectIdAndItemIdAsync(Guid projectId, uint itemId);
|
||||||
|
|
||||||
@@ -34,5 +34,5 @@ internal interface ICultivationDbService
|
|||||||
|
|
||||||
void UpdateCultivateItem(CultivateItem item);
|
void UpdateCultivateItem(CultivateItem item);
|
||||||
|
|
||||||
void UpdateInventoryItem(InventoryItem item);
|
ValueTask UpdateCultivateItemAsync(CultivateItem item);
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,15 @@ internal sealed partial class DailyNoteDbService : IDailyNoteDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask<bool> ContainsUidAsync(string uid)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
return await appDbContext.DailyNotes.AsNoTracking().AnyAsync(n => n.Uid == uid).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async ValueTask AddDailyNoteEntryAsync(DailyNoteEntry entry)
|
public async ValueTask AddDailyNoteEntryAsync(DailyNoteEntry entry)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -50,15 +59,6 @@ internal sealed partial class DailyNoteDbService : IDailyNoteDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DailyNoteEntry> GetDailyNoteEntryList()
|
|
||||||
{
|
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
|
||||||
{
|
|
||||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
|
||||||
return appDbContext.DailyNotes.AsNoTracking().ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DailyNoteEntry> GetDailyNoteEntryIncludeUserList()
|
public List<DailyNoteEntry> GetDailyNoteEntryIncludeUserList()
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -67,4 +67,13 @@ internal sealed partial class DailyNoteDbService : IDailyNoteDbService
|
|||||||
return appDbContext.DailyNotes.AsNoTracking().Include(n => n.User).ToList();
|
return appDbContext.DailyNotes.AsNoTracking().Include(n => n.User).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask<List<DailyNoteEntry>> GetDailyNoteEntryIncludeUserListAsync()
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
return await appDbContext.DailyNotes.AsNoTracking().Include(n => n.User).ToListAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ internal sealed partial class DailyNoteService : IDailyNoteService, IRecipient<U
|
|||||||
{
|
{
|
||||||
string roleUid = userAndUid.Uid.Value;
|
string roleUid = userAndUid.Uid.Value;
|
||||||
|
|
||||||
if (!dailyNoteDbService.ContainsUid(roleUid))
|
if (!await dailyNoteDbService.ContainsUidAsync(roleUid).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
DailyNoteEntry newEntry = DailyNoteEntry.From(userAndUid);
|
DailyNoteEntry newEntry = DailyNoteEntry.From(userAndUid);
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ internal sealed partial class DailyNoteService : IDailyNoteService, IRecipient<U
|
|||||||
await userService.GetRoleCollectionAsync().ConfigureAwait(false);
|
await userService.GetRoleCollectionAsync().ConfigureAwait(false);
|
||||||
await RefreshDailyNotesCoreAsync(forceRefresh).ConfigureAwait(false);
|
await RefreshDailyNotesCoreAsync(forceRefresh).ConfigureAwait(false);
|
||||||
|
|
||||||
List<DailyNoteEntry> entryList = dailyNoteDbService.GetDailyNoteEntryIncludeUserList();
|
List<DailyNoteEntry> entryList = await dailyNoteDbService.GetDailyNoteEntryIncludeUserListAsync().ConfigureAwait(false);
|
||||||
entryList.ForEach(entry => { entry.UserGameRole = userService.GetUserGameRoleByUid(entry.Uid); });
|
entryList.ForEach(entry => { entry.UserGameRole = userService.GetUserGameRoleByUid(entry.Uid); });
|
||||||
entries = new(entryList);
|
entries = new(entryList);
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ internal sealed partial class DailyNoteService : IDailyNoteService, IRecipient<U
|
|||||||
|
|
||||||
private async ValueTask RefreshDailyNotesCoreAsync(bool forceRefresh)
|
private async ValueTask RefreshDailyNotesCoreAsync(bool forceRefresh)
|
||||||
{
|
{
|
||||||
foreach (DailyNoteEntry entry in dailyNoteDbService.GetDailyNoteEntryIncludeUserList())
|
foreach (DailyNoteEntry entry in await dailyNoteDbService.GetDailyNoteEntryIncludeUserListAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
if (!forceRefresh && entry.DailyNote is not null)
|
if (!forceRefresh && entry.DailyNote is not null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ internal interface IDailyNoteDbService
|
|||||||
|
|
||||||
bool ContainsUid(string uid);
|
bool ContainsUid(string uid);
|
||||||
|
|
||||||
|
ValueTask<bool> ContainsUidAsync(string uid);
|
||||||
|
|
||||||
ValueTask DeleteDailyNoteEntryByIdAsync(Guid entryId);
|
ValueTask DeleteDailyNoteEntryByIdAsync(Guid entryId);
|
||||||
|
|
||||||
List<DailyNoteEntry> GetDailyNoteEntryIncludeUserList();
|
List<DailyNoteEntry> GetDailyNoteEntryIncludeUserList();
|
||||||
|
|
||||||
List<DailyNoteEntry> GetDailyNoteEntryList();
|
ValueTask<List<DailyNoteEntry>> GetDailyNoteEntryIncludeUserListAsync();
|
||||||
|
|
||||||
ValueTask UpdateDailyNoteEntryAsync(DailyNoteEntry entry);
|
ValueTask UpdateDailyNoteEntryAsync(DailyNoteEntry entry);
|
||||||
}
|
}
|
||||||
@@ -49,10 +49,10 @@ internal readonly struct GachaItemSaveContext
|
|||||||
// 全量刷新
|
// 全量刷新
|
||||||
if (!IsLazy)
|
if (!IsLazy)
|
||||||
{
|
{
|
||||||
GachaLogDbService.DeleteNewerGachaItemsByArchiveIdQueryTypeAndEndId(archive.InnerId, QueryType, EndId);
|
GachaLogDbService.RemoveNewerGachaItemRangeByArchiveIdQueryTypeAndEndId(archive.InnerId, QueryType, EndId);
|
||||||
}
|
}
|
||||||
|
|
||||||
GachaLogDbService.AddGachaItems(ItemsToAdd);
|
GachaLogDbService.AddGachaItemRange(ItemsToAdd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,21 @@ internal sealed partial class GachaLogDbService : IGachaLogDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask DeleteGachaArchiveByIdAsync(Guid archiveId)
|
public async ValueTask<List<GachaItem>> GetGachaItemListByArchiveIdAsync(Guid archiveId)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
return await appDbContext.GachaItems
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(i => i.ArchiveId == archiveId)
|
||||||
|
.OrderBy(i => i.Id)
|
||||||
|
.ToListAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask RemoveGachaArchiveByIdAsync(Guid archiveId)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -118,6 +132,36 @@ internal sealed partial class GachaLogDbService : IGachaLogDbService
|
|||||||
return item?.Id ?? 0L;
|
return item?.Id ?? 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask<long> GetNewestGachaItemIdByArchiveIdAndQueryTypeAsync(Guid archiveId, GachaConfigType queryType)
|
||||||
|
{
|
||||||
|
GachaItem? item = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
|
||||||
|
// TODO: replace with MaxBy
|
||||||
|
// https://github.com/dotnet/efcore/issues/25566
|
||||||
|
// .MaxBy(i => i.Id);
|
||||||
|
item = await appDbContext.GachaItems
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(i => i.ArchiveId == archiveId)
|
||||||
|
.Where(i => i.QueryType == queryType)
|
||||||
|
.OrderByDescending(i => i.Id)
|
||||||
|
.FirstOrDefaultAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SqliteException ex)
|
||||||
|
{
|
||||||
|
ThrowHelper.UserdataCorrupted(SH.ServiceGachaLogEndIdUserdataCorruptedMessage, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return item?.Id ?? 0L;
|
||||||
|
}
|
||||||
|
|
||||||
public long GetOldestGachaItemIdByArchiveId(Guid archiveId)
|
public long GetOldestGachaItemIdByArchiveId(Guid archiveId)
|
||||||
{
|
{
|
||||||
GachaItem? item = null;
|
GachaItem? item = null;
|
||||||
@@ -139,6 +183,28 @@ internal sealed partial class GachaLogDbService : IGachaLogDbService
|
|||||||
return item?.Id ?? long.MaxValue;
|
return item?.Id ?? long.MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask<long> GetOldestGachaItemIdByArchiveIdAsync(Guid archiveId)
|
||||||
|
{
|
||||||
|
GachaItem? item = null;
|
||||||
|
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
|
||||||
|
// TODO: replace with MaxBy
|
||||||
|
// https://github.com/dotnet/efcore/issues/25566
|
||||||
|
// .MaxBy(i => i.Id);
|
||||||
|
item = await appDbContext.GachaItems
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(i => i.ArchiveId == archiveId)
|
||||||
|
.OrderBy(i => i.Id)
|
||||||
|
.FirstOrDefaultAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return item?.Id ?? long.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
public long GetOldestGachaItemIdByArchiveIdAndQueryType(Guid archiveId, GachaConfigType queryType)
|
public long GetOldestGachaItemIdByArchiveIdAndQueryType(Guid archiveId, GachaConfigType queryType)
|
||||||
{
|
{
|
||||||
GachaItem? item = null;
|
GachaItem? item = null;
|
||||||
@@ -182,15 +248,6 @@ internal sealed partial class GachaLogDbService : IGachaLogDbService
|
|||||||
return item?.Id ?? long.MaxValue;
|
return item?.Id ?? long.MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask AddGachaArchiveAsync(GachaArchive archive)
|
|
||||||
{
|
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
|
||||||
{
|
|
||||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
|
||||||
await appDbContext.GachaArchives.AddAndSaveAsync(archive).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddGachaArchive(GachaArchive archive)
|
public void AddGachaArchive(GachaArchive archive)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -200,6 +257,15 @@ internal sealed partial class GachaLogDbService : IGachaLogDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask AddGachaArchiveAsync(GachaArchive archive)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.GachaArchives.AddAndSaveAsync(archive).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<Web.Hutao.GachaLog.GachaItem> GetHutaoGachaItemList(Guid archiveId, GachaConfigType queryType, long endId)
|
public List<Web.Hutao.GachaLog.GachaItem> GetHutaoGachaItemList(Guid archiveId, GachaConfigType queryType, long endId)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -225,6 +291,32 @@ internal sealed partial class GachaLogDbService : IGachaLogDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask<List<Web.Hutao.GachaLog.GachaItem>> GetHutaoGachaItemListAsync(Guid archiveId, GachaConfigType queryType, long endId)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
return await appDbContext.GachaItems
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(i => i.ArchiveId == archiveId)
|
||||||
|
.Where(i => i.QueryType == queryType)
|
||||||
|
.OrderByDescending(i => i.Id)
|
||||||
|
.Where(i => i.Id > endId)
|
||||||
|
|
||||||
|
// Keep this to make SQL generates correctly
|
||||||
|
.Select(i => new Web.Hutao.GachaLog.GachaItem()
|
||||||
|
{
|
||||||
|
GachaType = i.GachaType,
|
||||||
|
QueryType = i.QueryType,
|
||||||
|
ItemId = i.ItemId,
|
||||||
|
Time = i.Time,
|
||||||
|
Id = i.Id,
|
||||||
|
})
|
||||||
|
.ToListAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async ValueTask<GachaArchive?> GetGachaArchiveByIdAsync(Guid archiveId, CancellationToken token)
|
public async ValueTask<GachaArchive?> GetGachaArchiveByIdAsync(Guid archiveId, CancellationToken token)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -258,7 +350,7 @@ internal sealed partial class GachaLogDbService : IGachaLogDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddGachaItems(List<GachaItem> items)
|
public void AddGachaItemRange(List<GachaItem> items)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -267,7 +359,16 @@ internal sealed partial class GachaLogDbService : IGachaLogDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteNewerGachaItemsByArchiveIdQueryTypeAndEndId(Guid archiveId, GachaConfigType queryType, long endId)
|
public async ValueTask AddGachaItemRangeAsync(List<GachaItem> items)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.GachaItems.AddRangeAndSaveAsync(items).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveNewerGachaItemRangeByArchiveIdQueryTypeAndEndId(Guid archiveId, GachaConfigType queryType, long endId)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -279,4 +380,18 @@ internal sealed partial class GachaLogDbService : IGachaLogDbService
|
|||||||
.ExecuteDelete();
|
.ExecuteDelete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async ValueTask RemoveNewerGachaItemRangeByArchiveIdQueryTypeAndEndIdAsync(Guid archiveId, GachaConfigType queryType, long endId)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.GachaItems
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(i => i.ArchiveId == archiveId && i.QueryType == queryType)
|
||||||
|
.Where(i => i.Id >= endId)
|
||||||
|
.ExecuteDeleteAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,9 @@ internal sealed partial class GachaLogHutaoCloudService : IGachaLogHutaoCloudSer
|
|||||||
List<Web.Hutao.GachaLog.GachaItem> items = new();
|
List<Web.Hutao.GachaLog.GachaItem> items = new();
|
||||||
foreach ((GachaConfigType type, long endId) in endIds)
|
foreach ((GachaConfigType type, long endId) in endIds)
|
||||||
{
|
{
|
||||||
List<Web.Hutao.GachaLog.GachaItem> part = gachaLogDbService.GetHutaoGachaItemList(gachaArchive.InnerId, type, endId);
|
List<Web.Hutao.GachaLog.GachaItem> part = await gachaLogDbService
|
||||||
|
.GetHutaoGachaItemListAsync(gachaArchive.InnerId, type, endId)
|
||||||
|
.ConfigureAwait(false);
|
||||||
items.AddRange(part);
|
items.AddRange(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ internal sealed partial class GachaLogService : IGachaLogService
|
|||||||
// Return statistics
|
// Return statistics
|
||||||
using (ValueStopwatch.MeasureExecution(logger))
|
using (ValueStopwatch.MeasureExecution(logger))
|
||||||
{
|
{
|
||||||
List<GachaItem> items = gachaLogDbService.GetGachaItemListByArchiveId(archive.InnerId);
|
List<GachaItem> items = await gachaLogDbService.GetGachaItemListByArchiveIdAsync(archive.InnerId).ConfigureAwait(false);
|
||||||
return await gachaStatisticsFactory.CreateAsync(items, context).ConfigureAwait(false);
|
return await gachaStatisticsFactory.CreateAsync(items, context).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ internal sealed partial class GachaLogService : IGachaLogService
|
|||||||
List<GachaStatisticsSlim> statistics = new();
|
List<GachaStatisticsSlim> statistics = new();
|
||||||
foreach (GachaArchive archive in ArchiveCollection)
|
foreach (GachaArchive archive in ArchiveCollection)
|
||||||
{
|
{
|
||||||
List<GachaItem> items = gachaLogDbService.GetGachaItemListByArchiveId(archive.InnerId);
|
List<GachaItem> items = await gachaLogDbService.GetGachaItemListByArchiveIdAsync(archive.InnerId).ConfigureAwait(false);
|
||||||
GachaStatisticsSlim slim = await gachaStatisticsSlimFactory.CreateAsync(context, items, archive.Uid).ConfigureAwait(false);
|
GachaStatisticsSlim slim = await gachaStatisticsSlimFactory.CreateAsync(context, items, archive.Uid).ConfigureAwait(false);
|
||||||
statistics.Add(slim);
|
statistics.Add(slim);
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,7 @@ internal sealed partial class GachaLogService : IGachaLogService
|
|||||||
|
|
||||||
// Sync database
|
// Sync database
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
await gachaLogDbService.DeleteGachaArchiveByIdAsync(archive.InnerId).ConfigureAwait(false);
|
await gachaLogDbService.RemoveGachaArchiveByIdAsync(archive.InnerId).ConfigureAwait(false);
|
||||||
|
|
||||||
// Sync cache
|
// Sync cache
|
||||||
await taskContext.SwitchToMainThreadAsync();
|
await taskContext.SwitchToMainThreadAsync();
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ internal interface IGachaLogDbService
|
|||||||
|
|
||||||
ValueTask AddGachaArchiveAsync(GachaArchive archive);
|
ValueTask AddGachaArchiveAsync(GachaArchive archive);
|
||||||
|
|
||||||
void AddGachaItems(List<GachaItem> items);
|
void AddGachaItemRange(List<GachaItem> items);
|
||||||
|
|
||||||
ValueTask AddGachaItemsAsync(List<GachaItem> items);
|
ValueTask AddGachaItemsAsync(List<GachaItem> items);
|
||||||
|
|
||||||
ValueTask DeleteGachaArchiveByIdAsync(Guid archiveId);
|
ValueTask RemoveGachaArchiveByIdAsync(Guid archiveId);
|
||||||
|
|
||||||
void DeleteNewerGachaItemsByArchiveIdQueryTypeAndEndId(Guid archiveId, GachaConfigType queryType, long endId);
|
void RemoveNewerGachaItemRangeByArchiveIdQueryTypeAndEndId(Guid archiveId, GachaConfigType queryType, long endId);
|
||||||
|
|
||||||
ValueTask<GachaArchive?> GetGachaArchiveByIdAsync(Guid archiveId, CancellationToken token);
|
ValueTask<GachaArchive?> GetGachaArchiveByIdAsync(Guid archiveId, CancellationToken token);
|
||||||
|
|
||||||
@@ -29,6 +29,8 @@ internal interface IGachaLogDbService
|
|||||||
|
|
||||||
List<GachaItem> GetGachaItemListByArchiveId(Guid archiveId);
|
List<GachaItem> GetGachaItemListByArchiveId(Guid archiveId);
|
||||||
|
|
||||||
|
ValueTask<List<GachaItem>> GetGachaItemListByArchiveIdAsync(Guid archiveId);
|
||||||
|
|
||||||
List<Web.Hutao.GachaLog.GachaItem> GetHutaoGachaItemList(Guid archiveId, GachaConfigType queryType, long endId);
|
List<Web.Hutao.GachaLog.GachaItem> GetHutaoGachaItemList(Guid archiveId, GachaConfigType queryType, long endId);
|
||||||
|
|
||||||
long GetNewestGachaItemIdByArchiveIdAndQueryType(Guid archiveId, GachaConfigType queryType);
|
long GetNewestGachaItemIdByArchiveIdAndQueryType(Guid archiveId, GachaConfigType queryType);
|
||||||
@@ -40,4 +42,14 @@ internal interface IGachaLogDbService
|
|||||||
long GetOldestGachaItemIdByArchiveIdAndQueryType(Guid archiveId, GachaConfigType queryType);
|
long GetOldestGachaItemIdByArchiveIdAndQueryType(Guid archiveId, GachaConfigType queryType);
|
||||||
|
|
||||||
ValueTask<long> GetOldestGachaItemIdByArchiveIdAndQueryTypeAsync(Guid archiveId, GachaConfigType queryType, CancellationToken token);
|
ValueTask<long> GetOldestGachaItemIdByArchiveIdAndQueryTypeAsync(Guid archiveId, GachaConfigType queryType, CancellationToken token);
|
||||||
|
|
||||||
|
ValueTask<long> GetNewestGachaItemIdByArchiveIdAndQueryTypeAsync(Guid archiveId, GachaConfigType queryType);
|
||||||
|
|
||||||
|
ValueTask<long> GetOldestGachaItemIdByArchiveIdAsync(Guid archiveId);
|
||||||
|
|
||||||
|
ValueTask<List<Web.Hutao.GachaLog.GachaItem>> GetHutaoGachaItemListAsync(Guid archiveId, GachaConfigType queryType, long endId);
|
||||||
|
|
||||||
|
ValueTask AddGachaItemRangeAsync(List<GachaItem> items);
|
||||||
|
|
||||||
|
ValueTask RemoveNewerGachaItemRangeByArchiveIdQueryTypeAndEndIdAsync(Guid archiveId, GachaConfigType queryType, long endId);
|
||||||
}
|
}
|
||||||
@@ -24,10 +24,10 @@ internal sealed partial class UIGFExportService : IUIGFExportService
|
|||||||
public async ValueTask<UIGF> ExportAsync(GachaLogServiceMetadataContext context, GachaArchive archive)
|
public async ValueTask<UIGF> ExportAsync(GachaLogServiceMetadataContext context, GachaArchive archive)
|
||||||
{
|
{
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
|
List<GachaItem> entities = await gachaLogDbService
|
||||||
List<UIGFItem> list = gachaLogDbService
|
.GetGachaItemListByArchiveIdAsync(archive.InnerId)
|
||||||
.GetGachaItemListByArchiveId(archive.InnerId)
|
.ConfigureAwait(false);
|
||||||
.SelectList(i => UIGFItem.From(i, context.GetNameQualityByItemId(i.ItemId)));
|
List<UIGFItem> list = entities.SelectList(i => UIGFItem.From(i, context.GetNameQualityByItemId(i.ItemId)));
|
||||||
|
|
||||||
UIGF uigf = new()
|
UIGF uigf = new()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,15 +33,6 @@ internal sealed partial class GameDbService : IGameDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask UpdateGameAccountAsync(GameAccount gameAccount)
|
|
||||||
{
|
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
|
||||||
{
|
|
||||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
|
||||||
await appDbContext.GameAccounts.UpdateAndSaveAsync(gameAccount).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateGameAccount(GameAccount gameAccount)
|
public void UpdateGameAccount(GameAccount gameAccount)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
@@ -51,7 +42,16 @@ internal sealed partial class GameDbService : IGameDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask DeleteGameAccountByIdAsync(Guid id)
|
public async ValueTask UpdateGameAccountAsync(GameAccount gameAccount)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.GameAccounts.UpdateAndSaveAsync(gameAccount).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask RemoveGameAccountByIdAsync(Guid id)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -386,16 +386,6 @@ internal sealed partial class GameService : IGameService
|
|||||||
gameAccounts.Remove(gameAccount);
|
gameAccounts.Remove(gameAccount);
|
||||||
|
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
await gameDbService.DeleteGameAccountByIdAsync(gameAccount.InnerId).ConfigureAwait(false);
|
await gameDbService.RemoveGameAccountByIdAsync(gameAccount.InnerId).ConfigureAwait(false);
|
||||||
}
|
|
||||||
|
|
||||||
private static bool LaunchSchemeMatchesExecutable(LaunchScheme launchScheme, string gameFileName)
|
|
||||||
{
|
|
||||||
return (launchScheme.IsOversea, gameFileName) switch
|
|
||||||
{
|
|
||||||
(true, GenshinImpactFileName) => true,
|
|
||||||
(false, YuanShenFileName) => true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ internal interface IGameDbService
|
|||||||
{
|
{
|
||||||
ValueTask AddGameAccountAsync(GameAccount gameAccount);
|
ValueTask AddGameAccountAsync(GameAccount gameAccount);
|
||||||
|
|
||||||
ValueTask DeleteGameAccountByIdAsync(Guid id);
|
ValueTask RemoveGameAccountByIdAsync(Guid id);
|
||||||
|
|
||||||
ObservableCollection<GameAccount> GetGameAccountCollection();
|
ObservableCollection<GameAccount> GetGameAccountCollection();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Model.Entity;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Inventroy;
|
||||||
|
|
||||||
|
internal interface IInventoryDbService
|
||||||
|
{
|
||||||
|
ValueTask AddInventoryItemRangeByProjectId(List<InventoryItem> items);
|
||||||
|
|
||||||
|
ValueTask RemoveInventoryItemRangeByProjectId(Guid projectId);
|
||||||
|
|
||||||
|
void UpdateInventoryItem(InventoryItem item);
|
||||||
|
|
||||||
|
ValueTask UpdateInventoryItemAsync(InventoryItem item);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Inventroy;
|
||||||
|
|
||||||
|
internal interface IInventoryService
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Snap.Hutao.Core.Database;
|
||||||
|
using Snap.Hutao.Model.Entity;
|
||||||
|
using Snap.Hutao.Model.Entity.Database;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Inventroy;
|
||||||
|
|
||||||
|
[ConstructorGenerated]
|
||||||
|
[Injection(InjectAs.Singleton, typeof(IInventoryDbService))]
|
||||||
|
internal sealed partial class InventoryDbService : IInventoryDbService
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider serviceProvider;
|
||||||
|
|
||||||
|
public async ValueTask RemoveInventoryItemRangeByProjectId(Guid projectId)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.InventoryItems
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(a => a.ProjectId == projectId && a.ItemId != 202U) // 摩拉
|
||||||
|
.ExecuteDeleteAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask AddInventoryItemRangeByProjectId(List<InventoryItem> items)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.InventoryItems.AddRangeAndSaveAsync(items).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateInventoryItem(InventoryItem item)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.InventoryItems.UpdateAndSave(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask UpdateInventoryItemAsync(InventoryItem item)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.InventoryItems.UpdateAndSaveAsync(item).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Inventroy;
|
||||||
|
|
||||||
|
[Injection(InjectAs.Transient)]
|
||||||
|
internal sealed class InventoryService : IInventoryService
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ internal interface IUserDbService
|
|||||||
|
|
||||||
ValueTask DeleteUserByIdAsync(Guid id);
|
ValueTask DeleteUserByIdAsync(Guid id);
|
||||||
|
|
||||||
ValueTask DeleteUsersAsync();
|
ValueTask RemoveUsersAsync();
|
||||||
|
|
||||||
ValueTask<List<Model.Entity.User>> GetUserListAsync();
|
ValueTask<List<Model.Entity.User>> GetUserListAsync();
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ internal sealed partial class UserDbService : IUserDbService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask DeleteUsersAsync()
|
public async ValueTask RemoveUsersAsync()
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ internal sealed partial class UserService : IUserService, IUserServiceUnsafe
|
|||||||
public async ValueTask UnsafeRemoveUsersAsync()
|
public async ValueTask UnsafeRemoveUsersAsync()
|
||||||
{
|
{
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
await userDbService.DeleteUsersAsync().ConfigureAwait(false);
|
await userDbService.RemoveUsersAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
<None Remove="LaunchGameWindow.xaml" />
|
<None Remove="LaunchGameWindow.xaml" />
|
||||||
<None Remove="NativeMethods.json" />
|
<None Remove="NativeMethods.json" />
|
||||||
<None Remove="NativeMethods.txt" />
|
<None Remove="NativeMethods.txt" />
|
||||||
|
<None Remove="Resource\BlurBackground.png" />
|
||||||
<None Remove="Resource\Font\CascadiaMono.ttf" />
|
<None Remove="Resource\Font\CascadiaMono.ttf" />
|
||||||
<None Remove="Resource\Font\MiSans-Regular.ttf" />
|
<None Remove="Resource\Font\MiSans-Regular.ttf" />
|
||||||
<None Remove="Resource\HutaoIconSourceTransparentBackgroundGradient1.png" />
|
<None Remove="Resource\HutaoIconSourceTransparentBackgroundGradient1.png" />
|
||||||
@@ -206,6 +207,7 @@
|
|||||||
|
|
||||||
<!-- Resources Files -->
|
<!-- Resources Files -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Content Include="Resource\BlurBackground.png" />
|
||||||
<Content Include="Resource\Font\CascadiaMono.ttf" />
|
<Content Include="Resource\Font\CascadiaMono.ttf" />
|
||||||
<Content Include="Resource\Font\MiSans-Regular.ttf" />
|
<Content Include="Resource\Font\MiSans-Regular.ttf" />
|
||||||
<Content Include="Resource\HutaoIconSourceTransparentBackgroundGradient1.png" />
|
<Content Include="Resource\HutaoIconSourceTransparentBackgroundGradient1.png" />
|
||||||
@@ -239,12 +241,12 @@
|
|||||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.TokenView" Version="0.1.230809" />
|
<PackageReference Include="CommunityToolkit.Labs.WinUI.TokenView" Version="0.1.230809" />
|
||||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.TransitionHelper" Version="0.1.230809" />
|
<PackageReference Include="CommunityToolkit.Labs.WinUI.TransitionHelper" Version="0.1.230809" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2-build.1" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2-build.1" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Behaviors" Version="8.0.230828-rc" />
|
<PackageReference Include="CommunityToolkit.WinUI.Behaviors" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.HeaderedControls" Version="8.0.230828-rc" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.HeaderedControls" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.0.230828-rc" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.0.230828-rc" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.230828-rc" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.230828-rc" />
|
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Core" Version="7.1.2" />
|
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Core" Version="7.1.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.10" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.10" />
|
||||||
|
|||||||
11
src/Snap.Hutao/Snap.Hutao/View/Card/CardReference.cs
Normal file
11
src/Snap.Hutao/Snap.Hutao/View/Card/CardReference.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.View.Card;
|
||||||
|
|
||||||
|
internal sealed class CardReference
|
||||||
|
{
|
||||||
|
public Button? Card { get; set; }
|
||||||
|
}
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Margin="0,8,0,0"
|
Margin="0,8,0,0"
|
||||||
Visibility="{Binding Weapon, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
|
Visibility="{x:Bind Weapon, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
|
||||||
<Border Style="{StaticResource BorderCardStyle}">
|
<Border Style="{StaticResource BorderCardStyle}">
|
||||||
<Grid Margin="8" DataContext="{x:Bind Weapon}">
|
<Grid Margin="8" DataContext="{x:Bind Weapon}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
|
|||||||
@@ -76,11 +76,7 @@
|
|||||||
Margin="2,6,3,6"
|
Margin="2,6,3,6"
|
||||||
DisplayMemberPath="Name"
|
DisplayMemberPath="Name"
|
||||||
ItemsSource="{Binding Archives, Mode=OneWay}"
|
ItemsSource="{Binding Archives, Mode=OneWay}"
|
||||||
SelectedItem="{Binding SelectedArchive, Mode=TwoWay}">
|
SelectedItem="{Binding SelectedArchive, Mode=TwoWay}"/>
|
||||||
<mxi:Interaction.Behaviors>
|
|
||||||
<shcb:ComboBoxExtendsContentIntoTitleBarWorkaroundBehavior/>
|
|
||||||
</mxi:Interaction.Behaviors>
|
|
||||||
</ComboBox>
|
|
||||||
</AppBarElementContainer>
|
</AppBarElementContainer>
|
||||||
<AppBarButton
|
<AppBarButton
|
||||||
Command="{Binding AddArchiveCommand}"
|
Command="{Binding AddArchiveCommand}"
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
xmlns:cwa="using:CommunityToolkit.WinUI.Animations"
|
xmlns:cwa="using:CommunityToolkit.WinUI.Animations"
|
||||||
xmlns:cwb="using:CommunityToolkit.WinUI.Behaviors"
|
xmlns:cwb="using:CommunityToolkit.WinUI.Behaviors"
|
||||||
xmlns:cwu="using:CommunityToolkit.WinUI.UI"
|
xmlns:cwu="using:CommunityToolkit.WinUI.UI"
|
||||||
xmlns:cwucont="using:CommunityToolkit.WinUI.UI.Controls"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
||||||
@@ -15,7 +14,6 @@
|
|||||||
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
||||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||||
xmlns:shvca="using:Snap.Hutao.View.Card"
|
|
||||||
xmlns:shvco="using:Snap.Hutao.View.Control"
|
xmlns:shvco="using:Snap.Hutao.View.Control"
|
||||||
xmlns:shvh="using:Snap.Hutao.ViewModel.Home"
|
xmlns:shvh="using:Snap.Hutao.ViewModel.Home"
|
||||||
d:DataContext="{d:DesignInstance shvh:AnnouncementViewModel}"
|
d:DataContext="{d:DesignInstance shvh:AnnouncementViewModel}"
|
||||||
@@ -29,140 +27,147 @@
|
|||||||
<shc:BindingProxy x:Key="BindingProxy" DataContext="{Binding}"/>
|
<shc:BindingProxy x:Key="BindingProxy" DataContext="{Binding}"/>
|
||||||
|
|
||||||
<DataTemplate x:Key="AnnouncementTemplate">
|
<DataTemplate x:Key="AnnouncementTemplate">
|
||||||
<cwucont:AdaptiveGridView
|
<ItemsView
|
||||||
Margin="16,16,0,-4"
|
Margin="16"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
cwa:ItemsReorderAnimation.Duration="0:0:0.1"
|
IsItemInvokedEnabled="False"
|
||||||
DesiredWidth="{StaticResource AdaptiveGridViewDesiredWidth}"
|
|
||||||
ItemContainerStyle="{StaticResource LargeGridViewItemStyle}"
|
|
||||||
ItemsSource="{Binding List}"
|
ItemsSource="{Binding List}"
|
||||||
SelectionMode="None">
|
SelectionMode="None">
|
||||||
<cwucont:AdaptiveGridView.ItemTemplate>
|
<ItemsView.Layout>
|
||||||
|
<UniformGridLayout
|
||||||
|
ItemsJustification="Start"
|
||||||
|
ItemsStretch="Fill"
|
||||||
|
MinColumnSpacing="12"
|
||||||
|
MinItemWidth="300"
|
||||||
|
MinRowSpacing="12"/>
|
||||||
|
</ItemsView.Layout>
|
||||||
|
<ItemsView.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Border cwu:UIElementExtensions.ClipToBounds="True" Style="{StaticResource BorderCardStyle}">
|
<ItemContainer>
|
||||||
<Grid>
|
<Border Style="{StaticResource BorderCardStyle}">
|
||||||
<Grid.RowDefinitions>
|
<Grid>
|
||||||
<RowDefinition/>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="auto"/>
|
<RowDefinition/>
|
||||||
</Grid.RowDefinitions>
|
<RowDefinition Height="auto"/>
|
||||||
<!-- Image Layer -->
|
</Grid.RowDefinitions>
|
||||||
<Border cwu:UIElementExtensions.ClipToBounds="True">
|
<!-- Image Layer -->
|
||||||
<Border VerticalAlignment="Top" cwu:VisualExtensions.NormalizedCenterPoint="0.5">
|
<Border cwu:UIElementExtensions.ClipToBounds="True">
|
||||||
<shci:CachedImage Source="{Binding Banner}" Stretch="UniformToFill"/>
|
<Border VerticalAlignment="Top" cwu:VisualExtensions.NormalizedCenterPoint="0.5">
|
||||||
|
<shci:CachedImage Source="{Binding Banner}" Stretch="UniformToFill"/>
|
||||||
|
|
||||||
<mxi:Interaction.Behaviors>
|
<mxi:Interaction.Behaviors>
|
||||||
<shcb:AutoHeightBehavior TargetHeight="390" TargetWidth="1080"/>
|
<shcb:AutoHeightBehavior TargetHeight="390" TargetWidth="1080"/>
|
||||||
</mxi:Interaction.Behaviors>
|
</mxi:Interaction.Behaviors>
|
||||||
<cwa:Explicit.Animations>
|
<cwa:Explicit.Animations>
|
||||||
<cwa:AnimationSet x:Name="ImageZoomInAnimation">
|
<cwa:AnimationSet x:Name="ImageZoomInAnimation">
|
||||||
<shca:ImageZoomInAnimation/>
|
<shca:ImageZoomInAnimation/>
|
||||||
</cwa:AnimationSet>
|
</cwa:AnimationSet>
|
||||||
<cwa:AnimationSet x:Name="ImageZoomOutAnimation">
|
<cwa:AnimationSet x:Name="ImageZoomOutAnimation">
|
||||||
<shca:ImageZoomOutAnimation/>
|
<shca:ImageZoomOutAnimation/>
|
||||||
</cwa:AnimationSet>
|
</cwa:AnimationSet>
|
||||||
</cwa:Explicit.Animations>
|
</cwa:Explicit.Animations>
|
||||||
|
</Border>
|
||||||
</Border>
|
</Border>
|
||||||
</Border>
|
<!-- Time Description -->
|
||||||
<!-- Time Description -->
|
<Grid Grid.Row="0">
|
||||||
<Grid Grid.Row="0">
|
<Border
|
||||||
<Border
|
HorizontalAlignment="Stretch"
|
||||||
Height="24"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
VerticalAlignment="Bottom"
|
|
||||||
Visibility="{Binding ShouldShowTimeDescription, Converter={StaticResource BoolToVisibilityConverter}}">
|
|
||||||
<ProgressBar
|
|
||||||
MinHeight="2"
|
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
Background="Transparent"
|
Visibility="{Binding ShouldShowTimeDescription, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||||
CornerRadius="0"
|
<ProgressBar
|
||||||
Maximum="1"
|
MinHeight="2"
|
||||||
Value="{Binding TimePercent, Mode=OneWay}"/>
|
VerticalAlignment="Bottom"
|
||||||
|
Background="Transparent"
|
||||||
|
CornerRadius="0"
|
||||||
|
Maximum="1"
|
||||||
|
Value="{Binding TimePercent, Mode=OneWay}"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
<!-- General Description -->
|
||||||
|
<Border Grid.Row="1" CornerRadius="{StaticResource CompatCornerRadiusBottom}">
|
||||||
|
<StackPanel Margin="4" VerticalAlignment="Bottom">
|
||||||
|
<TextBlock
|
||||||
|
Margin="4,6,0,0"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Style="{StaticResource SubtitleTextBlockStyle}"
|
||||||
|
Text="{Binding Subtitle}"
|
||||||
|
TextTrimming="WordEllipsis"
|
||||||
|
TextWrapping="NoWrap"/>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="4,6,0,0"
|
||||||
|
Opacity="0.6"
|
||||||
|
Style="{StaticResource BodyTextBlockStyle}"
|
||||||
|
Text="{Binding Title}"
|
||||||
|
TextTrimming="WordEllipsis"
|
||||||
|
TextWrapping="NoWrap"/>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock
|
||||||
|
Margin="4,4,0,4"
|
||||||
|
FontSize="10"
|
||||||
|
Opacity="0.4"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{Binding TimeFormatted}"
|
||||||
|
TextWrapping="NoWrap"/>
|
||||||
|
<TextBlock
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="4,4,4,4"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
VerticalAlignment="Bottom"
|
||||||
|
FontSize="10"
|
||||||
|
Opacity="0.8"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{Binding TimeDescription}"
|
||||||
|
Visibility="{Binding ShouldShowTimeDescription, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
<!-- General Description -->
|
<FlyoutBase.AttachedFlyout>
|
||||||
<Border Grid.Row="1" CornerRadius="{StaticResource CompatCornerRadiusBottom}">
|
<Flyout LightDismissOverlayMode="On" Placement="Full">
|
||||||
<StackPanel Margin="4" VerticalAlignment="Bottom">
|
<Flyout.FlyoutPresenterStyle>
|
||||||
<TextBlock
|
<Style BasedOn="{StaticResource DefaultFlyoutPresenterStyle}" TargetType="FlyoutPresenter">
|
||||||
Margin="4,6,0,0"
|
<Setter Property="Padding" Value="0"/>
|
||||||
HorizontalAlignment="Stretch"
|
<Setter Property="CornerRadius" Value="0"/>
|
||||||
Style="{StaticResource SubtitleTextBlockStyle}"
|
<Setter Property="MaxWidth" Value="640"/>
|
||||||
Text="{Binding Subtitle}"
|
</Style>
|
||||||
TextTrimming="WordEllipsis"
|
</Flyout.FlyoutPresenterStyle>
|
||||||
TextWrapping="NoWrap"/>
|
<shvco:AnnouncementContentViewer Announcement="{Binding}"/>
|
||||||
|
</Flyout>
|
||||||
<TextBlock
|
</FlyoutBase.AttachedFlyout>
|
||||||
Margin="4,6,0,0"
|
<mxi:Interaction.Behaviors>
|
||||||
Opacity="0.6"
|
<mxic:EventTriggerBehavior EventName="Tapped">
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
<shcb:OpenAttachedFlyoutAction/>
|
||||||
Text="{Binding Title}"
|
</mxic:EventTriggerBehavior>
|
||||||
TextTrimming="WordEllipsis"
|
<mxic:EventTriggerBehavior EventName="PointerEntered">
|
||||||
TextWrapping="NoWrap"/>
|
<cwb:StartAnimationAction Animation="{Binding ElementName=ImageZoomInAnimation}"/>
|
||||||
|
</mxic:EventTriggerBehavior>
|
||||||
<Grid>
|
<mxic:EventTriggerBehavior EventName="PointerExited">
|
||||||
<Grid.ColumnDefinitions>
|
<cwb:StartAnimationAction Animation="{Binding ElementName=ImageZoomOutAnimation}"/>
|
||||||
<ColumnDefinition/>
|
</mxic:EventTriggerBehavior>
|
||||||
<ColumnDefinition Width="auto"/>
|
</mxi:Interaction.Behaviors>
|
||||||
</Grid.ColumnDefinitions>
|
</Border>
|
||||||
<TextBlock
|
</ItemContainer>
|
||||||
Margin="4,4,0,4"
|
|
||||||
FontSize="10"
|
|
||||||
Opacity="0.4"
|
|
||||||
Style="{StaticResource CaptionTextBlockStyle}"
|
|
||||||
Text="{Binding TimeFormatted}"
|
|
||||||
TextWrapping="NoWrap"/>
|
|
||||||
<TextBlock
|
|
||||||
Grid.Column="1"
|
|
||||||
Margin="4,4,4,4"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
VerticalAlignment="Bottom"
|
|
||||||
FontSize="10"
|
|
||||||
Opacity="0.8"
|
|
||||||
Style="{StaticResource CaptionTextBlockStyle}"
|
|
||||||
Text="{Binding TimeDescription}"
|
|
||||||
Visibility="{Binding ShouldShowTimeDescription, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
|
||||||
</Grid>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
|
||||||
<FlyoutBase.AttachedFlyout>
|
|
||||||
<Flyout LightDismissOverlayMode="On" Placement="Full">
|
|
||||||
<Flyout.FlyoutPresenterStyle>
|
|
||||||
<Style BasedOn="{StaticResource DefaultFlyoutPresenterStyle}" TargetType="FlyoutPresenter">
|
|
||||||
<Setter Property="Padding" Value="0"/>
|
|
||||||
<Setter Property="CornerRadius" Value="0"/>
|
|
||||||
<Setter Property="MaxWidth" Value="640"/>
|
|
||||||
</Style>
|
|
||||||
</Flyout.FlyoutPresenterStyle>
|
|
||||||
<shvco:AnnouncementContentViewer Announcement="{Binding}"/>
|
|
||||||
</Flyout>
|
|
||||||
</FlyoutBase.AttachedFlyout>
|
|
||||||
<mxi:Interaction.Behaviors>
|
|
||||||
<mxic:EventTriggerBehavior EventName="Tapped">
|
|
||||||
<shcb:OpenAttachedFlyoutAction/>
|
|
||||||
</mxic:EventTriggerBehavior>
|
|
||||||
<mxic:EventTriggerBehavior EventName="PointerEntered">
|
|
||||||
<cwb:StartAnimationAction Animation="{Binding ElementName=ImageZoomInAnimation}"/>
|
|
||||||
</mxic:EventTriggerBehavior>
|
|
||||||
<mxic:EventTriggerBehavior EventName="PointerExited">
|
|
||||||
<cwb:StartAnimationAction Animation="{Binding ElementName=ImageZoomOutAnimation}"/>
|
|
||||||
</mxic:EventTriggerBehavior>
|
|
||||||
</mxi:Interaction.Behaviors>
|
|
||||||
</Border>
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</cwucont:AdaptiveGridView.ItemTemplate>
|
</ItemsView.ItemTemplate>
|
||||||
</cwucont:AdaptiveGridView>
|
</ItemsView>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</shc:ScopedPage.Resources>
|
</shc:ScopedPage.Resources>
|
||||||
<Grid>
|
<Grid>
|
||||||
<ScrollViewer Padding="0,0,4,0">
|
<ScrollViewer Padding="0,0,0,0">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
|
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="16,16,12,0"
|
Margin="16,16,16,0"
|
||||||
Style="{StaticResource TitleTextBlockStyle}"
|
Style="{StaticResource TitleTextBlockStyle}"
|
||||||
Text="{Binding GreetingText}"/>
|
Text="{Binding GreetingText}"/>
|
||||||
<TextBlock Margin="16,0,16,0" Text="{Binding UserOptions.UserName}"/>
|
<TextBlock Margin="16,0" Text="{Binding UserOptions.UserName}"/>
|
||||||
|
|
||||||
<ItemsControl
|
<ItemsControl
|
||||||
Margin="16,16,12,0"
|
Margin="16,16,12,0"
|
||||||
@@ -190,26 +195,33 @@
|
|||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
|
|
||||||
<cwucont:AdaptiveGridView
|
<ItemsView
|
||||||
Margin="16,16,0,0"
|
Margin="16"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
cwa:ItemsReorderAnimation.Duration="0:0:0.1"
|
IsItemInvokedEnabled="False"
|
||||||
DesiredWidth="{StaticResource AdaptiveGridViewDesiredWidth}"
|
ItemsSource="{Binding Cards, Mode=OneWay}"
|
||||||
ItemContainerStyle="{StaticResource LargeGridViewItemStyle}"
|
|
||||||
SelectionMode="None"
|
SelectionMode="None"
|
||||||
StretchContentForSingleRow="False">
|
Visibility="{Binding Cards.Count, Converter={StaticResource Int32ToVisibilityConverter}}">
|
||||||
<shvca:LaunchGameCard Height="{StaticResource HomeAdaptiveCardHeight}"/>
|
<ItemsView.Layout>
|
||||||
<shvca:GachaStatisticsCard/>
|
<UniformGridLayout
|
||||||
<shvca:AchievementCard/>
|
ItemsJustification="Start"
|
||||||
<shvca:DailyNoteCard/>
|
ItemsStretch="Fill"
|
||||||
|
MinColumnSpacing="12"
|
||||||
<!--<Border Style="{StaticResource BorderCardStyle}">
|
MinItemHeight="180"
|
||||||
<TextBlock Text="养成计划"/>
|
MinItemWidth="300"
|
||||||
</Border>
|
MinRowSpacing="12"/>
|
||||||
<Border Style="{StaticResource BorderCardStyle}">
|
</ItemsView.Layout>
|
||||||
<TextBlock Text="深渊"/>
|
<ItemsView.ItemTemplate>
|
||||||
</Border>-->
|
<DataTemplate>
|
||||||
</cwucont:AdaptiveGridView>
|
<ItemContainer>
|
||||||
|
<ItemContainer.Resources>
|
||||||
|
<SolidColorBrush x:Key="ItemContainerPointerOverBackground" Color="Transparent"/>
|
||||||
|
</ItemContainer.Resources>
|
||||||
|
<ContentControl HorizontalContentAlignment="Stretch" Content="{Binding Card}"/>
|
||||||
|
</ItemContainer>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsView.ItemTemplate>
|
||||||
|
</ItemsView>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<Pivot Style="{StaticResource DefaultPivotStyle}">
|
<Pivot Style="{StaticResource DefaultPivotStyle}">
|
||||||
|
|||||||
@@ -66,11 +66,7 @@
|
|||||||
Margin="6,6,6,6"
|
Margin="6,6,6,6"
|
||||||
DisplayMemberPath="Name"
|
DisplayMemberPath="Name"
|
||||||
ItemsSource="{Binding Projects}"
|
ItemsSource="{Binding Projects}"
|
||||||
SelectedItem="{Binding SelectedProject, Mode=TwoWay}">
|
SelectedItem="{Binding SelectedProject, Mode=TwoWay}"/>
|
||||||
<mxi:Interaction.Behaviors>
|
|
||||||
<shcb:ComboBoxExtendsContentIntoTitleBarWorkaroundBehavior/>
|
|
||||||
</mxi:Interaction.Behaviors>
|
|
||||||
</ComboBox>
|
|
||||||
</AppBarElementContainer>
|
</AppBarElementContainer>
|
||||||
<AppBarButton
|
<AppBarButton
|
||||||
Command="{Binding AddProjectCommand}"
|
Command="{Binding AddProjectCommand}"
|
||||||
|
|||||||
@@ -36,11 +36,7 @@
|
|||||||
Margin="16,6,0,6"
|
Margin="16,6,0,6"
|
||||||
DisplayMemberPath="Uid"
|
DisplayMemberPath="Uid"
|
||||||
ItemsSource="{Binding Archives}"
|
ItemsSource="{Binding Archives}"
|
||||||
SelectedItem="{Binding SelectedArchive, Mode=TwoWay}">
|
SelectedItem="{Binding SelectedArchive, Mode=TwoWay}"/>
|
||||||
<mxi:Interaction.Behaviors>
|
|
||||||
<shcb:ComboBoxExtendsContentIntoTitleBarWorkaroundBehavior/>
|
|
||||||
</mxi:Interaction.Behaviors>
|
|
||||||
</ComboBox>
|
|
||||||
</Pivot.LeftHeader>
|
</Pivot.LeftHeader>
|
||||||
<Pivot.RightHeader>
|
<Pivot.RightHeader>
|
||||||
<CommandBar DefaultLabelPosition="Right">
|
<CommandBar DefaultLabelPosition="Right">
|
||||||
|
|||||||
@@ -23,9 +23,9 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<Image
|
<Image
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Source="ms-appx:///Assets/Square44x44Logo.targetsize-256.png"
|
Source="ms-appx:///Resource/BlurBackground.png"
|
||||||
Stretch="UniformToFill"/>
|
Stretch="Fill"/>
|
||||||
<Grid Background="{ThemeResource AcrylicInAppFillColorDefaultBrush}">
|
<Grid Background="{ThemeResource SystemControlBackgroundAltMediumBrush}">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition/>
|
<RowDefinition/>
|
||||||
<RowDefinition Height="auto"/>
|
<RowDefinition Height="auto"/>
|
||||||
@@ -91,6 +91,8 @@
|
|||||||
Description="{Binding HutaoOptions.WebView2Version}"
|
Description="{Binding HutaoOptions.WebView2Version}"
|
||||||
Header="{shcm:ResourceString Name=ViewPageSettingWebview2Header}"
|
Header="{shcm:ResourceString Name=ViewPageSettingWebview2Header}"
|
||||||
HeaderIcon="{shcm:FontIcon Glyph=}"/>
|
HeaderIcon="{shcm:FontIcon Glyph=}"/>
|
||||||
|
|
||||||
|
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingShellExperienceHeader}"/>
|
||||||
<cwc:SettingsCard
|
<cwc:SettingsCard
|
||||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingCreateDesktopShortcutAction}"
|
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingCreateDesktopShortcutAction}"
|
||||||
Command="{Binding CreateDesktopShortcutCommand}"
|
Command="{Binding CreateDesktopShortcutCommand}"
|
||||||
@@ -119,28 +121,68 @@
|
|||||||
SelectedItem="{Binding SelectedBackdropType, Mode=TwoWay}"/>
|
SelectedItem="{Binding SelectedBackdropType, Mode=TwoWay}"/>
|
||||||
</cwc:SettingsCard>
|
</cwc:SettingsCard>
|
||||||
|
|
||||||
|
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewpageSettingHomeHeader}"/>
|
||||||
|
<cwc:SettingsExpander
|
||||||
|
Description="{shcm:ResourceString Name=ViewpageSettingHomeCardDescription}"
|
||||||
|
Header="{shcm:ResourceString Name=ViewpageSettingHomeCardHeader}"
|
||||||
|
HeaderIcon="{shcm:FontIcon Glyph=}">
|
||||||
|
<cwc:SettingsExpander.Items>
|
||||||
|
<cwc:SettingsCard Header="{shcm:ResourceString Name=ViewpageSettingHomeCardItemLaunchGameHeader}">
|
||||||
|
<ToggleSwitch
|
||||||
|
IsOn="{Binding HomeCardOptions.IsHomeCardLaunchGamePresented, Mode=TwoWay}"
|
||||||
|
OffContent="{shcm:ResourceString Name=ViewPageSettingHomeCardOff}"
|
||||||
|
OnContent="{shcm:ResourceString Name=ViewPageSettingHomeCardOn}"/>
|
||||||
|
</cwc:SettingsCard>
|
||||||
|
<cwc:SettingsCard Header="{shcm:ResourceString Name=ViewpageSettingHomeCardItemgachaStatisticsHeader}">
|
||||||
|
<ToggleSwitch
|
||||||
|
IsOn="{Binding HomeCardOptions.IsHomeCardGachaStatisticsPresented, Mode=TwoWay}"
|
||||||
|
OffContent="{shcm:ResourceString Name=ViewPageSettingHomeCardOff}"
|
||||||
|
OnContent="{shcm:ResourceString Name=ViewPageSettingHomeCardOn}"/>
|
||||||
|
</cwc:SettingsCard>
|
||||||
|
<cwc:SettingsCard Header="{shcm:ResourceString Name=ViewpageSettingHomeCardItemAchievementHeader}">
|
||||||
|
<ToggleSwitch
|
||||||
|
IsOn="{Binding HomeCardOptions.IsHomeCardAchievementPresented, Mode=TwoWay}"
|
||||||
|
OffContent="{shcm:ResourceString Name=ViewPageSettingHomeCardOff}"
|
||||||
|
OnContent="{shcm:ResourceString Name=ViewPageSettingHomeCardOn}"/>
|
||||||
|
</cwc:SettingsCard>
|
||||||
|
<cwc:SettingsCard Header="{shcm:ResourceString Name=ViewpageSettingHomeCardItemDailyNoteHeader}">
|
||||||
|
<ToggleSwitch
|
||||||
|
IsOn="{Binding HomeCardOptions.IsHomeCardDailyNotePresented, Mode=TwoWay}"
|
||||||
|
OffContent="{shcm:ResourceString Name=ViewPageSettingHomeCardOff}"
|
||||||
|
OnContent="{shcm:ResourceString Name=ViewPageSettingHomeCardOn}"/>
|
||||||
|
</cwc:SettingsCard>
|
||||||
|
</cwc:SettingsExpander.Items>
|
||||||
|
</cwc:SettingsExpander>
|
||||||
|
|
||||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingGameHeader}"/>
|
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingGameHeader}"/>
|
||||||
<InfoBar
|
|
||||||
IsClosable="False"
|
|
||||||
IsOpen="True"
|
|
||||||
Message="{shcm:ResourceString Name=ViewPageSettingSetGamePathHint}"
|
|
||||||
Severity="Informational"/>
|
|
||||||
<cwc:SettingsCard
|
<cwc:SettingsCard
|
||||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingSetGamePathAction}"
|
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingSetGamePathAction}"
|
||||||
Command="{Binding SetGamePathCommand}"
|
Command="{Binding SetGamePathCommand}"
|
||||||
Description="{Binding Options.GamePath}"
|
|
||||||
Header="{shcm:ResourceString Name=ViewPageSettingSetGamePathHeader}"
|
Header="{shcm:ResourceString Name=ViewPageSettingSetGamePathHeader}"
|
||||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||||
IsClickEnabled="True"/>
|
IsClickEnabled="True">
|
||||||
|
<cwc:SettingsCard.Description>
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Foreground="{ThemeResource SystemErrorTextColor}" Text="{shcm:ResourceString Name=ViewPageSettingSetGamePathHint}"/>
|
||||||
|
<TextBlock Text="{Binding Options.GamePath}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</cwc:SettingsCard.Description>
|
||||||
|
</cwc:SettingsCard>
|
||||||
<cwc:SettingsCard
|
<cwc:SettingsCard
|
||||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingSetGamePathAction}"
|
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingSetGamePathAction}"
|
||||||
Command="{Binding SetPowerShellPathCommand}"
|
Command="{Binding SetPowerShellPathCommand}"
|
||||||
Description="{Binding Options.PowerShellPath}"
|
|
||||||
Header="{shcm:ResourceString Name=ViewPageSettingSetPowerShellPathHeader}"
|
Header="{shcm:ResourceString Name=ViewPageSettingSetPowerShellPathHeader}"
|
||||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||||
IsClickEnabled="True"/>
|
IsClickEnabled="True">
|
||||||
|
<cwc:SettingsCard.Description>
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="{shcm:ResourceString Name=ViewPageSettingSetPowerShellDescription}"/>
|
||||||
|
<TextBlock Text="{Binding Options.PowerShellPath}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</cwc:SettingsCard.Description>
|
||||||
|
</cwc:SettingsCard>
|
||||||
<cwc:SettingsCard
|
<cwc:SettingsCard
|
||||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingDeleteCacheAction}"
|
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingDeleteCacheAction}"
|
||||||
|
|||||||
@@ -315,6 +315,7 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
|||||||
|
|
||||||
if (result.Interrupted)
|
if (result.Interrupted)
|
||||||
{
|
{
|
||||||
|
infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
|
||||||
infoBarService.Warning(SH.ViewModelCultivationBatchAddIncompletedFormat.Format(result.SucceedCount, result.SkippedCount));
|
infoBarService.Warning(SH.ViewModelCultivationBatchAddIncompletedFormat.Format(result.SucceedCount, result.SkippedCount));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
// 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 Microsoft.UI.Xaml.Controls;
|
||||||
using Snap.Hutao.Core.Setting;
|
using Snap.Hutao.Core.Setting;
|
||||||
using Snap.Hutao.Service.Abstraction;
|
using Snap.Hutao.Service.Abstraction;
|
||||||
using Snap.Hutao.Service.Hutao;
|
using Snap.Hutao.Service.Hutao;
|
||||||
|
using Snap.Hutao.View.Card;
|
||||||
using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement;
|
using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
@@ -25,6 +27,7 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
|
|||||||
private AnnouncementWrapper? announcement;
|
private AnnouncementWrapper? announcement;
|
||||||
private string greetingText = SH.ViewPageHomeGreetingTextDefault;
|
private string greetingText = SH.ViewPageHomeGreetingTextDefault;
|
||||||
private ObservableCollection<Web.Hutao.HutaoAsAService.Announcement>? hutaoAnnouncements;
|
private ObservableCollection<Web.Hutao.HutaoAsAService.Announcement>? hutaoAnnouncements;
|
||||||
|
private List<CardReference>? cards;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 公告
|
/// 公告
|
||||||
@@ -43,8 +46,11 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string GreetingText { get => greetingText; set => SetProperty(ref greetingText, value); }
|
public string GreetingText { get => greetingText; set => SetProperty(ref greetingText, value); }
|
||||||
|
|
||||||
|
public List<CardReference>? Cards { get => cards; set => SetProperty(ref cards, value); }
|
||||||
|
|
||||||
protected override ValueTask<bool> InitializeUIAsync()
|
protected override ValueTask<bool> InitializeUIAsync()
|
||||||
{
|
{
|
||||||
|
InitializeDashboard();
|
||||||
InitializeInGameAnnouncementAsync().SafeForget();
|
InitializeInGameAnnouncementAsync().SafeForget();
|
||||||
InitializeHutaoAnnouncementAsync().SafeForget();
|
InitializeHutaoAnnouncementAsync().SafeForget();
|
||||||
UpdateGreetingText();
|
UpdateGreetingText();
|
||||||
@@ -105,4 +111,31 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeDashboard()
|
||||||
|
{
|
||||||
|
List<CardReference> result = new();
|
||||||
|
|
||||||
|
if (LocalSetting.Get(SettingKeys.IsHomeCardLaunchGamePresented, true))
|
||||||
|
{
|
||||||
|
result.Add(new() { Card = new LaunchGameCard() });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LocalSetting.Get(SettingKeys.IsHomeCardGachaStatisticsPresented, true))
|
||||||
|
{
|
||||||
|
result.Add(new() { Card = new GachaStatisticsCard() });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LocalSetting.Get(SettingKeys.IsHomeCardAchievementPresented, true))
|
||||||
|
{
|
||||||
|
result.Add(new() { Card = new AchievementCard() });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LocalSetting.Get(SettingKeys.IsHomeCardDailyNotePresented, true))
|
||||||
|
{
|
||||||
|
result.Add(new() { Card = new DailyNoteCard() });
|
||||||
|
}
|
||||||
|
|
||||||
|
Cards = result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
33
src/Snap.Hutao/Snap.Hutao/ViewModel/HomeCardOptions.cs
Normal file
33
src/Snap.Hutao/Snap.Hutao/ViewModel/HomeCardOptions.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Core.Setting;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.ViewModel;
|
||||||
|
|
||||||
|
internal sealed class HomeCardOptions
|
||||||
|
{
|
||||||
|
public bool IsHomeCardLaunchGamePresented
|
||||||
|
{
|
||||||
|
get => LocalSetting.Get(SettingKeys.IsHomeCardLaunchGamePresented, true);
|
||||||
|
set => LocalSetting.Set(SettingKeys.IsHomeCardLaunchGamePresented, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsHomeCardGachaStatisticsPresented
|
||||||
|
{
|
||||||
|
get => LocalSetting.Get(SettingKeys.IsHomeCardGachaStatisticsPresented, true);
|
||||||
|
set => LocalSetting.Set(SettingKeys.IsHomeCardGachaStatisticsPresented, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsHomeCardAchievementPresented
|
||||||
|
{
|
||||||
|
get => LocalSetting.Get(SettingKeys.IsHomeCardAchievementPresented, true);
|
||||||
|
set => LocalSetting.Set(SettingKeys.IsHomeCardAchievementPresented, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsHomeCardDailyNotePresented
|
||||||
|
{
|
||||||
|
get => LocalSetting.Get(SettingKeys.IsHomeCardDailyNotePresented, true);
|
||||||
|
set => LocalSetting.Set(SettingKeys.IsHomeCardDailyNotePresented, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,6 +37,8 @@ namespace Snap.Hutao.ViewModel;
|
|||||||
[Injection(InjectAs.Scoped)]
|
[Injection(InjectAs.Scoped)]
|
||||||
internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||||
{
|
{
|
||||||
|
private readonly HomeCardOptions homeCardOptions = new();
|
||||||
|
|
||||||
private readonly IContentDialogFactory contentDialogFactory;
|
private readonly IContentDialogFactory contentDialogFactory;
|
||||||
private readonly IGameLocatorFactory gameLocatorFactory;
|
private readonly IGameLocatorFactory gameLocatorFactory;
|
||||||
private readonly INavigationService navigationService;
|
private readonly INavigationService navigationService;
|
||||||
@@ -68,6 +70,8 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public HutaoUserOptions UserOptions { get => hutaoUserOptions; }
|
public HutaoUserOptions UserOptions { get => hutaoUserOptions; }
|
||||||
|
|
||||||
|
public HomeCardOptions HomeCardOptions { get => homeCardOptions; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 选中的背景类型
|
/// 选中的背景类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user