mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
launch game impl switch monitor
This commit is contained in:
@@ -253,4 +253,4 @@ internal static class LocalSetting
|
||||
{
|
||||
Container.Values[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ internal static class Localization
|
||||
/// <param name="culture">语言代码</param>
|
||||
public static void Initialize(string culture)
|
||||
{
|
||||
CultureInfo cultureInfo = CultureInfo.CreateSpecificCulture(culture);
|
||||
CultureInfo cultureInfo = CultureInfo.GetCultureInfo(culture);
|
||||
CultureInfo.CurrentCulture = cultureInfo;
|
||||
CultureInfo.CurrentUICulture = cultureInfo;
|
||||
ApplicationLanguages.PrimaryLanguageOverride = culture;
|
||||
|
||||
@@ -25,7 +25,7 @@ internal sealed class WindowSubclassManager<TWindow> : IDisposable
|
||||
private readonly bool isLegacyDragBar;
|
||||
private HWND hwndDragBar;
|
||||
|
||||
// We have to explictly hold a reference to SUBCLASSPROC
|
||||
// We have to explicitly hold a reference to SUBCLASSPROC
|
||||
private SUBCLASSPROC? windowProc;
|
||||
private SUBCLASSPROC? dragBarProc;
|
||||
|
||||
|
||||
@@ -81,6 +81,11 @@ internal sealed class SettingEntry
|
||||
/// </summary>
|
||||
public const string LaunchTargetFps = "Launch.TargetFps";
|
||||
|
||||
/// <summary>
|
||||
/// 启动游戏 显示器编号
|
||||
/// </summary>
|
||||
public const string LaunchMonitor = "Launch.Monitor";
|
||||
|
||||
/// <summary>
|
||||
/// 语言
|
||||
/// </summary>
|
||||
|
||||
@@ -6,6 +6,7 @@ using Snap.Hutao.Model.Calculable;
|
||||
using Snap.Hutao.Model.Metadata.Abstraction;
|
||||
using Snap.Hutao.Model.Metadata.Converter;
|
||||
using Snap.Hutao.Model.Metadata.Item;
|
||||
using Snap.Hutao.ViewModel.Complex;
|
||||
using Snap.Hutao.ViewModel.GachaLog;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Avatar;
|
||||
@@ -19,7 +20,7 @@ internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IName
|
||||
/// [非元数据] 搭配数据
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public ComplexAvatarCollocation? Collocation { get; set; }
|
||||
public AvatarCollocationView? Collocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// [非元数据] 烹饪奖励
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Model.Calculable;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata.Abstraction;
|
||||
using Snap.Hutao.Model.Metadata.Converter;
|
||||
using Snap.Hutao.ViewModel.Complex;
|
||||
using Snap.Hutao.ViewModel.GachaLog;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Weapon;
|
||||
@@ -19,7 +19,7 @@ internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource
|
||||
/// [非元数据] 搭配数据
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public ComplexWeaponCollocation? Collocation { get; set; }
|
||||
public WeaponCollocationView? Collocation { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
[JsonIgnore]
|
||||
|
||||
@@ -10,8 +10,11 @@ MINMAXINFO
|
||||
|
||||
// COMCTL32
|
||||
DefSubclassProc
|
||||
SetWindowSubclass
|
||||
RemoveWindowSubclass
|
||||
SetWindowSubclass
|
||||
|
||||
// GDI32
|
||||
GetDeviceCaps
|
||||
|
||||
// KERNEL32
|
||||
CreateEvent
|
||||
@@ -27,6 +30,7 @@ CoWaitForMultipleObjects
|
||||
|
||||
// USER32
|
||||
FindWindowEx
|
||||
GetDC
|
||||
GetDpiForWindow
|
||||
GetWindowPlacement
|
||||
|
||||
|
||||
136
src/Snap.Hutao/Snap.Hutao/Option/AppOptions.cs
Normal file
136
src/Snap.Hutao/Snap.Hutao/Option/AppOptions.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Snap.Hutao.Option;
|
||||
|
||||
/// <summary>
|
||||
/// 应用程序选项
|
||||
/// </summary>
|
||||
[Injection(InjectAs.Singleton)]
|
||||
internal sealed class AppOptions : IOptions<AppOptions>
|
||||
{
|
||||
private readonly IServiceScopeFactory serviceScopeFactory;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的应用程序选项
|
||||
/// </summary>
|
||||
/// <param name="serviceScopeFactory">服务范围工厂</param>
|
||||
public AppOptions(IServiceScopeFactory serviceScopeFactory)
|
||||
{
|
||||
this.serviceScopeFactory = serviceScopeFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 游戏路径
|
||||
/// </summary>
|
||||
public string? GamePath
|
||||
{
|
||||
get
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
return appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.GamePath)?.Value;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.GamePath);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.GamePath, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 游戏路径
|
||||
/// </summary>
|
||||
public bool IsEmptyHistoryWishVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.IsEmptyHistoryWishVisible)?.Value;
|
||||
return value != null && bool.Parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.IsEmptyHistoryWishVisible);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.IsEmptyHistoryWishVisible, value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 背景类型 默认 Mica
|
||||
/// </summary>
|
||||
public Core.Windowing.BackdropType BackdropType
|
||||
{
|
||||
get
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.SystemBackdropType)?.Value;
|
||||
return Enum.Parse<Core.Windowing.BackdropType>(value ?? nameof(Core.Windowing.BackdropType.Mica));
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.SystemBackdropType);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.SystemBackdropType, value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前语言
|
||||
/// </summary>
|
||||
public CultureInfo CurrentCulture
|
||||
{
|
||||
get
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.Culture)?.Value;
|
||||
return value != null ? CultureInfo.GetCultureInfo(value) : CultureInfo.CurrentCulture;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.Culture);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.Culture, value.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public AppOptions Value { get => this; }
|
||||
}
|
||||
@@ -59,7 +59,6 @@ public static partial class Program
|
||||
.AddDatabase()
|
||||
.AddInjections()
|
||||
.AddHttpClients()
|
||||
|
||||
// Discrete services
|
||||
.AddSingleton<IMessenger>(WeakReferenceMessenger.Default)
|
||||
|
||||
|
||||
@@ -2139,6 +2139,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 无圣遗物或散件 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewModelComplexReliquarySetViewEmptyName {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewModelComplexReliquarySetViewEmptyName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 养成计划添加失败 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3687,6 +3696,24 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 在指定的显示器上运行 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewPageLaunchGameMonitorsDescription {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewPageLaunchGameMonitorsDescription", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 显示器 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewPageLaunchGameMonitorsHeader {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewPageLaunchGameMonitorsHeader", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 在游戏时可以随时调整 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -810,6 +810,9 @@
|
||||
<data name="ViewModelAvatarPropertyShowcaseNotOpen" xml:space="preserve">
|
||||
<value>角色展柜尚未开启,请前往游戏操作后重试</value>
|
||||
</data>
|
||||
<data name="ViewModelComplexReliquarySetViewEmptyName" xml:space="preserve">
|
||||
<value>无圣遗物或散件</value>
|
||||
</data>
|
||||
<data name="ViewModelCultivationAddWarning" xml:space="preserve">
|
||||
<value>养成计划添加失败</value>
|
||||
</data>
|
||||
@@ -1326,6 +1329,12 @@
|
||||
<data name="ViewPageLaunchGameElevationHint" xml:space="preserve">
|
||||
<value>某些选项处于禁用状态,它们只在管理员模式下生效!</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameMonitorsDescription" xml:space="preserve">
|
||||
<value>在指定的显示器上运行</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameMonitorsHeader" xml:space="preserve">
|
||||
<value>显示器</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameSetFpsDescription" xml:space="preserve">
|
||||
<value>在游戏时可以随时调整</value>
|
||||
</data>
|
||||
|
||||
@@ -306,7 +306,7 @@ internal sealed class GameService : IGameService
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask LaunchAsync(LaunchConfiguration configuration)
|
||||
public async ValueTask LaunchAsync(LaunchOptions options)
|
||||
{
|
||||
if (IsGameRunning())
|
||||
{
|
||||
@@ -321,13 +321,13 @@ internal sealed class GameService : IGameService
|
||||
}
|
||||
|
||||
// https://docs.unity.cn/cn/current/Manual/PlayerCommandLineArguments.html
|
||||
// TODO: impl monitor option.
|
||||
string commandLine = new CommandLineBuilder()
|
||||
.AppendIf("-popupwindow", configuration.IsBorderless)
|
||||
.Append("-screen-fullscreen", configuration.IsFullScreen ? 1 : 0)
|
||||
.AppendIf("-window-mode", configuration.IsExclusive, "exclusive")
|
||||
.Append("-screen-width", configuration.ScreenWidth)
|
||||
.Append("-screen-height", configuration.ScreenHeight)
|
||||
.AppendIf("-popupwindow", options.IsBorderless)
|
||||
.Append("-screen-fullscreen", options.IsFullScreen ? 1 : 0)
|
||||
.AppendIf("-window-mode", options.IsExclusive, "exclusive")
|
||||
.Append("-screen-width", options.ScreenWidth)
|
||||
.Append("-screen-height", options.ScreenHeight)
|
||||
.Append("-monitor", options.Monitor.Value)
|
||||
.ToString();
|
||||
|
||||
Process game = new()
|
||||
@@ -344,9 +344,9 @@ internal sealed class GameService : IGameService
|
||||
|
||||
using (await gameSemaphore.EnterAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (configuration.UnlockFPS)
|
||||
if (options.UnlockFps)
|
||||
{
|
||||
IGameFpsUnlocker unlocker = new GameFpsUnlocker(game, configuration.TargetFPS);
|
||||
IGameFpsUnlocker unlocker = new GameFpsUnlocker(game, options.TargetFps);
|
||||
|
||||
TimeSpan findModuleDelay = TimeSpan.FromMilliseconds(100);
|
||||
TimeSpan findModuleLimit = TimeSpan.FromMilliseconds(10000);
|
||||
|
||||
@@ -61,9 +61,9 @@ internal interface IGameService
|
||||
/// <summary>
|
||||
/// 异步启动
|
||||
/// </summary>
|
||||
/// <param name="configuration">启动配置</param>
|
||||
/// <param name="options">启动配置</param>
|
||||
/// <returns>任务</returns>
|
||||
ValueTask LaunchAsync(LaunchConfiguration configuration);
|
||||
ValueTask LaunchAsync(LaunchOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// 异步修改游戏账号名称
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.Game;
|
||||
|
||||
/// <summary>
|
||||
/// 启动游戏配置
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal readonly struct LaunchConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否为独占全屏
|
||||
/// </summary>
|
||||
public readonly bool IsExclusive;
|
||||
|
||||
/// <summary>
|
||||
/// 是否全屏,全屏时无边框设置将被覆盖
|
||||
/// </summary>
|
||||
public readonly bool IsFullScreen;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为无边框窗口
|
||||
/// </summary>
|
||||
public readonly bool IsBorderless;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口宽度
|
||||
/// </summary>
|
||||
public readonly int ScreenWidth;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口高度
|
||||
/// </summary>
|
||||
public readonly int ScreenHeight;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用解锁帧率
|
||||
/// </summary>
|
||||
public readonly bool UnlockFPS;
|
||||
|
||||
/// <summary>
|
||||
/// 目标帧率
|
||||
/// </summary>
|
||||
public readonly int TargetFPS;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的启动配置
|
||||
/// </summary>
|
||||
/// <param name="isExclusive">独占全屏</param>
|
||||
/// <param name="isFullScreen">全屏</param>
|
||||
/// <param name="isBorderless">无边框</param>
|
||||
/// <param name="screenWidth">宽度</param>
|
||||
/// <param name="screenHeight">高度</param>
|
||||
/// <param name="unlockFps">解锁帧率</param>
|
||||
/// <param name="targetFps">目标帧率</param>
|
||||
public LaunchConfiguration(bool isExclusive, bool isFullScreen, bool isBorderless, int screenWidth, int screenHeight, bool unlockFps, int targetFps)
|
||||
{
|
||||
IsExclusive = isExclusive;
|
||||
IsFullScreen = isFullScreen;
|
||||
IsBorderless = isBorderless;
|
||||
ScreenHeight = screenHeight;
|
||||
ScreenWidth = screenWidth;
|
||||
ScreenHeight = screenHeight;
|
||||
UnlockFPS = unlockFps;
|
||||
TargetFPS = targetFps;
|
||||
}
|
||||
}
|
||||
371
src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs
Normal file
371
src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs
Normal file
@@ -0,0 +1,371 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Snap.Hutao.Win32;
|
||||
using Windows.Graphics;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Gdi;
|
||||
using static Windows.Win32.PInvoke;
|
||||
|
||||
namespace Snap.Hutao.Service.Game;
|
||||
|
||||
/// <summary>
|
||||
/// 启动游戏选项
|
||||
/// </summary>
|
||||
[Injection(InjectAs.Singleton)]
|
||||
internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
|
||||
{
|
||||
private readonly IServiceScopeFactory serviceScopeFactory;
|
||||
private readonly int primaryScreenWidth;
|
||||
private readonly int primaryScreenHeight;
|
||||
private readonly int primaryScreenFps;
|
||||
|
||||
private bool? isFullScreen;
|
||||
private bool? isBorderless;
|
||||
private bool? isExclusive;
|
||||
private int? screenWidth;
|
||||
private int? screenHeight;
|
||||
private bool? unlockFps;
|
||||
private int? targetFps;
|
||||
private NameValue<int>? monitor;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的启动游戏选项
|
||||
/// </summary>
|
||||
/// <param name="serviceScopeFactory">服务范围工厂</param>
|
||||
public LaunchOptions(IServiceScopeFactory serviceScopeFactory)
|
||||
{
|
||||
this.serviceScopeFactory = serviceScopeFactory;
|
||||
RectInt32 primaryRect = DisplayArea.Primary.OuterBounds;
|
||||
primaryScreenWidth = primaryRect.Width;
|
||||
primaryScreenHeight = primaryRect.Height;
|
||||
|
||||
// This list can't use foreach
|
||||
IReadOnlyList<DisplayArea> displayAreas = DisplayArea.FindAll();
|
||||
for (int i = 0; i < displayAreas.Count; i++)
|
||||
{
|
||||
DisplayArea displayArea = displayAreas[i];
|
||||
int index = i + 1;
|
||||
Monitors.Add(new($"{displayArea.DisplayId.Value:X8}:{index}", index));
|
||||
}
|
||||
|
||||
InitializeScreenFps(out primaryScreenFps);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否全屏
|
||||
/// </summary>
|
||||
public bool IsFullScreen
|
||||
{
|
||||
get
|
||||
{
|
||||
if (isFullScreen == null)
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchIsFullScreen)?.Value;
|
||||
isFullScreen = value != null && bool.Parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
return isFullScreen.Value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref isFullScreen, value))
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
IsBorderless = false;
|
||||
}
|
||||
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchIsFullScreen);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchIsFullScreen, value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否无边框
|
||||
/// </summary>
|
||||
public bool IsBorderless
|
||||
{
|
||||
get
|
||||
{
|
||||
if (isBorderless == null)
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchIsBorderless)?.Value;
|
||||
isBorderless = value != null && bool.Parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
return isBorderless.Value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref isBorderless, value))
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
IsExclusive = false;
|
||||
IsFullScreen = false;
|
||||
}
|
||||
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchIsBorderless);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchIsBorderless, value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否独占全屏
|
||||
/// </summary>
|
||||
public bool IsExclusive
|
||||
{
|
||||
get
|
||||
{
|
||||
if (isExclusive == null)
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchIsExclusive)?.Value;
|
||||
isExclusive = value != null && bool.Parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
return isExclusive.Value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref isExclusive, value))
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
IsFullScreen = true;
|
||||
}
|
||||
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchIsExclusive);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchIsExclusive, value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 屏幕宽度
|
||||
/// </summary>
|
||||
public int ScreenWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
if (screenWidth == null)
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchScreenWidth)?.Value;
|
||||
screenWidth = value == null ? primaryScreenWidth : int.Parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
return screenWidth.Value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref screenWidth, value))
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchScreenWidth);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchScreenWidth, value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 屏幕高度
|
||||
/// </summary>
|
||||
public int ScreenHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
if (screenHeight == null)
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchScreenHeight)?.Value;
|
||||
screenHeight = value == null ? primaryScreenHeight : int.Parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
return screenHeight.Value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref screenHeight, value))
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchScreenHeight);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchScreenHeight, value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否全屏
|
||||
/// </summary>
|
||||
public bool UnlockFps
|
||||
{
|
||||
get
|
||||
{
|
||||
if (unlockFps == null)
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchUnlockFps)?.Value;
|
||||
unlockFps = value != null && bool.Parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
return unlockFps.Value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref unlockFps, value))
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchUnlockFps);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchUnlockFps, value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 目标帧率
|
||||
/// </summary>
|
||||
public int TargetFps
|
||||
{
|
||||
get
|
||||
{
|
||||
if (targetFps == null)
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchTargetFps)?.Value;
|
||||
targetFps = value == null ? primaryScreenFps : int.Parse(value);
|
||||
}
|
||||
}
|
||||
|
||||
return targetFps.Value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref targetFps, value))
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchTargetFps);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchTargetFps, value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 所有监视器
|
||||
/// </summary>
|
||||
public List<NameValue<int>> Monitors { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 目标帧率
|
||||
/// </summary>
|
||||
public NameValue<int> Monitor
|
||||
{
|
||||
get
|
||||
{
|
||||
if (monitor == null)
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchMonitor)?.Value;
|
||||
|
||||
int index = value == null ? 1 : int.Parse(value);
|
||||
monitor = Monitors[index - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return monitor;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref monitor, value))
|
||||
{
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchMonitor);
|
||||
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchMonitor, value.Value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public LaunchOptions Value { get => this; }
|
||||
|
||||
private static void InitializeScreenFps(out int fps)
|
||||
{
|
||||
HDC hDC = GetDC(HWND.Null);
|
||||
fps = GetDeviceCaps(hDC, GET_DEVICE_CAPS_INDEX.VREFRESH);
|
||||
if (ReleaseDC(HWND.Null, hDC) == 0)
|
||||
{
|
||||
// not released
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.Model.Metadata.Weapon;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
using Snap.Hutao.Service.Metadata;
|
||||
using Snap.Hutao.ViewModel.Complex;
|
||||
using Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
namespace Snap.Hutao.Service.Hutao;
|
||||
@@ -40,25 +41,25 @@ internal sealed class HutaoCache : IHutaoCache
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public List<ComplexAvatarRank>? AvatarUsageRanks { get; set; }
|
||||
public List<AvatarRankView>? AvatarUsageRanks { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public List<ComplexAvatarRank>? AvatarAppearanceRanks { get; set; }
|
||||
public List<AvatarRankView>? AvatarAppearanceRanks { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public List<ComplexAvatarConstellationInfo>? AvatarConstellationInfos { get; set; }
|
||||
public List<AvatarConstellationInfoView>? AvatarConstellationInfos { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public List<ComplexTeamRank>? TeamAppearances { get; set; }
|
||||
public List<TeamAppearanceView>? TeamAppearances { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Overview? Overview { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public List<ComplexAvatarCollocation>? AvatarCollocations { get; set; }
|
||||
public List<AvatarCollocationView>? AvatarCollocations { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public List<ComplexWeaponCollocation>? WeaponCollocations { get; set; }
|
||||
public List<WeaponCollocationView>? WeaponCollocations { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask<bool> InitializeForDatabaseViewModelAsync()
|
||||
@@ -113,12 +114,12 @@ internal sealed class HutaoCache : IHutaoCache
|
||||
avatarCollocationsRaw = await hutaoService.GetAvatarCollocationsAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
AvatarCollocations = avatarCollocationsRaw.Select(co => new ComplexAvatarCollocation()
|
||||
AvatarCollocations = avatarCollocationsRaw.Select(co => new AvatarCollocationView()
|
||||
{
|
||||
AvatarId = co.AvatarId,
|
||||
Avatars = co.Avatars.Select(a => new ComplexAvatar(idAvatarMap[a.Item], a.Rate)).ToList(),
|
||||
Weapons = co.Weapons.Select(w => new ComplexWeapon(idWeaponMap[w.Item], w.Rate)).ToList(),
|
||||
ReliquarySets = co.Reliquaries.Select(r => new ComplexReliquarySet(r, idReliquarySetMap)).ToList(),
|
||||
Avatars = co.Avatars.Select(a => new AvatarView(idAvatarMap[a.Item], a.Rate)).ToList(),
|
||||
Weapons = co.Weapons.Select(w => new WeaponView(idWeaponMap[w.Item], w.Rate)).ToList(),
|
||||
ReliquarySets = co.Reliquaries.Select(r => new ReliquarySetView(r, idReliquarySetMap)).ToList(),
|
||||
}).ToList();
|
||||
|
||||
wikiAvatarViewModelTaskSource.TrySetResult(true);
|
||||
@@ -149,10 +150,10 @@ internal sealed class HutaoCache : IHutaoCache
|
||||
weaponCollocationsRaw = await hutaoService.GetWeaponCollocationsAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
WeaponCollocations = weaponCollocationsRaw.Select(co => new ComplexWeaponCollocation()
|
||||
WeaponCollocations = weaponCollocationsRaw.Select(co => new WeaponCollocationView()
|
||||
{
|
||||
WeaponId = co.WeaponId,
|
||||
Avatars = co.Avatars.Select(a => new ComplexAvatar(idAvatarMap[a.Item], a.Rate)).ToList(),
|
||||
Avatars = co.Avatars.Select(a => new AvatarView(idAvatarMap[a.Item], a.Rate)).ToList(),
|
||||
}).ToList();
|
||||
|
||||
wikiWeaponViewModelTaskSource.TrySetResult(true);
|
||||
@@ -183,10 +184,10 @@ internal sealed class HutaoCache : IHutaoCache
|
||||
avatarAppearanceRanksRaw = await hutaoService.GetAvatarAppearanceRanksAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
AvatarAppearanceRanks = avatarAppearanceRanksRaw.OrderByDescending(r => r.Floor).Select(rank => new ComplexAvatarRank
|
||||
AvatarAppearanceRanks = avatarAppearanceRanksRaw.OrderByDescending(r => r.Floor).Select(rank => new AvatarRankView
|
||||
{
|
||||
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, rank.Floor),
|
||||
Avatars = rank.Ranks.OrderByDescending(r => r.Rate).Select(rank => new ComplexAvatar(idAvatarMap[rank.Item], rank.Rate)).ToList(),
|
||||
Avatars = rank.Ranks.OrderByDescending(r => r.Rate).Select(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)).ToList(),
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
@@ -199,10 +200,10 @@ internal sealed class HutaoCache : IHutaoCache
|
||||
avatarUsageRanksRaw = await hutaoService.GetAvatarUsageRanksAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
AvatarUsageRanks = avatarUsageRanksRaw.OrderByDescending(r => r.Floor).Select(rank => new ComplexAvatarRank
|
||||
AvatarUsageRanks = avatarUsageRanksRaw.OrderByDescending(r => r.Floor).Select(rank => new AvatarRankView
|
||||
{
|
||||
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, rank.Floor),
|
||||
Avatars = rank.Ranks.OrderByDescending(r => r.Rate).Select(rank => new ComplexAvatar(idAvatarMap[rank.Item], rank.Rate)).ToList(),
|
||||
Avatars = rank.Ranks.OrderByDescending(r => r.Rate).Select(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)).ToList(),
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
@@ -217,7 +218,7 @@ internal sealed class HutaoCache : IHutaoCache
|
||||
|
||||
AvatarConstellationInfos = avatarConstellationInfosRaw.OrderBy(i => i.HoldingRate).Select(info =>
|
||||
{
|
||||
return new ComplexAvatarConstellationInfo(idAvatarMap[info.AvatarId], info.HoldingRate, info.Constellations.Select(x => x.Rate));
|
||||
return new AvatarConstellationInfoView(idAvatarMap[info.AvatarId], info.HoldingRate, info.Constellations.Select(x => x.Rate));
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
@@ -230,7 +231,7 @@ internal sealed class HutaoCache : IHutaoCache
|
||||
teamAppearancesRaw = await hutaoService.GetTeamAppearancesAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
TeamAppearances = teamAppearancesRaw.OrderByDescending(t => t.Floor).Select(team => new ComplexTeamRank(team, idAvatarMap)).ToList();
|
||||
TeamAppearances = teamAppearancesRaw.OrderByDescending(t => t.Floor).Select(team => new TeamAppearanceView(team, idAvatarMap)).ToList();
|
||||
}
|
||||
|
||||
private async Task OverviewAsync()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.ViewModel.Complex;
|
||||
using Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
namespace Snap.Hutao.Service.Hutao;
|
||||
@@ -15,22 +16,22 @@ internal interface IHutaoCache
|
||||
/// <summary>
|
||||
/// 角色使用率
|
||||
/// </summary>
|
||||
List<ComplexAvatarRank>? AvatarUsageRanks { get; set; }
|
||||
List<AvatarRankView>? AvatarUsageRanks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色上场率
|
||||
/// </summary>
|
||||
List<ComplexAvatarRank>? AvatarAppearanceRanks { get; set; }
|
||||
List<AvatarRankView>? AvatarAppearanceRanks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色命座信息
|
||||
/// </summary>
|
||||
List<ComplexAvatarConstellationInfo>? AvatarConstellationInfos { get; set; }
|
||||
List<AvatarConstellationInfoView>? AvatarConstellationInfos { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 队伍出场
|
||||
/// </summary>
|
||||
List<ComplexTeamRank>? TeamAppearances { get; set; }
|
||||
List<TeamAppearanceView>? TeamAppearances { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总览数据
|
||||
@@ -40,12 +41,12 @@ internal interface IHutaoCache
|
||||
/// <summary>
|
||||
/// 角色搭配
|
||||
/// </summary>
|
||||
List<ComplexAvatarCollocation>? AvatarCollocations { get; set; }
|
||||
List<AvatarCollocationView>? AvatarCollocations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 武器搭配
|
||||
/// </summary>
|
||||
List<ComplexWeaponCollocation>? WeaponCollocations { get; set; }
|
||||
List<WeaponCollocationView>? WeaponCollocations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 为数据库视图模型初始化
|
||||
|
||||
@@ -110,7 +110,6 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi
|
||||
case "id": return "ID"; // Indonesian
|
||||
case "it": return "IT"; // Italian
|
||||
case "ja": return "JP"; // Japanese
|
||||
case "kr": return "JP"; // Japanese
|
||||
case "ko": return "KR"; // Korean
|
||||
case "pt": return "PT"; // Portuguese
|
||||
case "ru": return "RU"; // Russian
|
||||
|
||||
@@ -432,7 +432,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Control\Extension\" />
|
||||
<Folder Include="Model\Binding\Gacha\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Resource\Localization\SH.Designer.cs">
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
xmlns:shcp="using:Snap.Hutao.Control.Panel"
|
||||
xmlns:shmbg="using:Snap.Hutao.Model.Binding.Gacha"
|
||||
xmlns:shvc="using:Snap.Hutao.View.Control"
|
||||
d:DataContext="{d:DesignInstance shmbg:Snap.Hutao.ViewModel.GachaLog.TypedWishSummary}"
|
||||
xmlns:shvg="using:Snap.Hutao.ViewModel.GachaLog"
|
||||
d:DataContext="{d:DesignInstance shvg:TypedWishSummary}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
@@ -19,7 +19,7 @@
|
||||
<SolidColorBrush x:Key="PurpleBrush" Color="#FFA156E0"/>
|
||||
<SolidColorBrush x:Key="OrangeBrush" Color="#FFBC6932"/>
|
||||
|
||||
<DataTemplate x:Key="OrangeListTemplate" x:DataType="shmbg:SummaryItem">
|
||||
<DataTemplate x:Key="OrangeListTemplate" d:DataType="shvg:SummaryItem">
|
||||
<Grid Margin="0,4,4,0" Background="Transparent">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock Text="{Binding TimeFormatted}"/>
|
||||
@@ -69,7 +69,7 @@
|
||||
FalseValue="{ThemeResource SystemFillColorCriticalBackgroundBrush}"
|
||||
TrueValue="{ThemeResource CardBackgroundFillColorDefaultBrush}"/>
|
||||
|
||||
<DataTemplate x:Key="OrangeGridTemplate" x:DataType="shmbg:SummaryItem">
|
||||
<DataTemplate x:Key="OrangeGridTemplate" d:DataType="shvg:SummaryItem">
|
||||
<Grid Width="40" Margin="0,4,4,0">
|
||||
<Border
|
||||
Background="{Binding IsUp, Converter={StaticResource BoolToBrushConverter}}"
|
||||
|
||||
@@ -9,11 +9,10 @@
|
||||
xmlns:shc="using:Snap.Hutao.Control"
|
||||
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
xmlns:shmbh="using:Snap.Hutao.Model.Binding.Hutao"
|
||||
xmlns:shv="using:Snap.Hutao.ViewModel"
|
||||
xmlns:shvc="using:Snap.Hutao.View.Control"
|
||||
xmlns:shvcom="using:Snap.Hutao.ViewModel.Complex"
|
||||
xmlns:shvcon="using:Snap.Hutao.View.Control"
|
||||
xmlns:wsc="using:WinUICommunity.SettingsUI.Controls"
|
||||
d:DataContext="{d:DesignInstance shv:HutaoDatabaseViewModel}"
|
||||
d:DataContext="{d:DesignInstance shvcom:HutaoDatabaseViewModel}"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
@@ -22,7 +21,7 @@
|
||||
</mxi:Interaction.Behaviors>
|
||||
|
||||
<Page.Resources>
|
||||
<DataTemplate x:Key="TeamItemTemplate" x:DataType="shmbh:Team">
|
||||
<DataTemplate x:Key="TeamItemTemplate" d:DataType="shvcom:Team">
|
||||
<Border Margin="12,0,12,12" Style="{StaticResource BorderCardStyle}">
|
||||
<Grid Margin="6">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -37,7 +36,7 @@
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<shvc:ItemIcon
|
||||
<shvcon:ItemIcon
|
||||
Width="48"
|
||||
Height="48"
|
||||
Icon="{Binding Icon}"
|
||||
@@ -115,9 +114,9 @@
|
||||
SelectionMode="None">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<shvc:BottomTextControl Text="{Binding Rate}">
|
||||
<shvc:ItemIcon Icon="{Binding Icon}" Quality="{Binding Quality}"/>
|
||||
</shvc:BottomTextControl>
|
||||
<shvcon:BottomTextControl Text="{Binding Rate}">
|
||||
<shvcon:ItemIcon Icon="{Binding Icon}" Quality="{Binding Quality}"/>
|
||||
</shvcon:BottomTextControl>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</GridView>
|
||||
@@ -143,9 +142,9 @@
|
||||
SelectionMode="None">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<shvc:BottomTextControl Text="{Binding Rate}">
|
||||
<shvc:ItemIcon Icon="{Binding Icon}" Quality="{Binding Quality}"/>
|
||||
</shvc:BottomTextControl>
|
||||
<shvcon:BottomTextControl Text="{Binding Rate}">
|
||||
<shvcon:ItemIcon Icon="{Binding Icon}" Quality="{Binding Quality}"/>
|
||||
</shvcon:BottomTextControl>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</GridView>
|
||||
@@ -275,7 +274,7 @@
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<shvc:ItemIcon
|
||||
<shvcon:ItemIcon
|
||||
Width="48"
|
||||
Height="48"
|
||||
Icon="{Binding Icon}"
|
||||
@@ -315,6 +314,6 @@
|
||||
</Grid>
|
||||
</PivotItem>
|
||||
</Pivot>
|
||||
<shvc:LoadingView IsLoading="{Binding Overview, Converter={StaticResource EmptyObjectToBoolRevertConverter}}"/>
|
||||
<shvcon:LoadingView IsLoading="{Binding Overview, Converter={StaticResource EmptyObjectToBoolRevertConverter}}"/>
|
||||
</Grid>
|
||||
</shc:ScopedPage>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.ViewModel;
|
||||
using Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
namespace Snap.Hutao.View.Page;
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
<wsc:Setting.ActionContent>
|
||||
<ToggleSwitch
|
||||
Width="120"
|
||||
IsOn="{Binding IsExclusive, Mode=TwoWay}"
|
||||
IsOn="{Binding Options.IsExclusive, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
@@ -195,7 +195,7 @@
|
||||
<wsc:Setting.ActionContent>
|
||||
<ToggleSwitch
|
||||
Width="120"
|
||||
IsOn="{Binding IsFullScreen, Mode=TwoWay}"
|
||||
IsOn="{Binding Options.IsFullScreen, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
@@ -206,7 +206,7 @@
|
||||
<wsc:Setting.ActionContent>
|
||||
<ToggleSwitch
|
||||
Width="120"
|
||||
IsOn="{Binding IsBorderless, Mode=TwoWay}"
|
||||
IsOn="{Binding Options.IsBorderless, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
@@ -217,7 +217,7 @@
|
||||
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenWidthHeader}"
|
||||
Icon="">
|
||||
<wsc:Setting.ActionContent>
|
||||
<NumberBox Width="156" Value="{Binding ScreenWidth, Mode=TwoWay}"/>
|
||||
<NumberBox Width="156" Value="{Binding Options.ScreenWidth, Mode=TwoWay}"/>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
<wsc:Setting
|
||||
@@ -225,7 +225,19 @@
|
||||
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenHeightHeader}"
|
||||
Icon="">
|
||||
<wsc:Setting.ActionContent>
|
||||
<NumberBox Width="156" Value="{Binding ScreenHeight, Mode=TwoWay}"/>
|
||||
<NumberBox Width="156" Value="{Binding Options.ScreenHeight, Mode=TwoWay}"/>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
|
||||
<wsc:Setting
|
||||
Description="{shcm:ResourceString Name=ViewPageLaunchGameMonitorsDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageLaunchGameMonitorsHeader}"
|
||||
Icon="">
|
||||
<wsc:Setting.ActionContent>
|
||||
<ComboBox
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding Options.Monitors}"
|
||||
SelectedItem="{Binding Options.Monitor, Mode=TwoWay}"/>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
</wsc:SettingsGroup>
|
||||
@@ -243,7 +255,7 @@
|
||||
<wsc:Setting.ActionContent>
|
||||
<ToggleSwitch
|
||||
Width="120"
|
||||
IsOn="{Binding UnlockFps, Mode=TwoWay}"
|
||||
IsOn="{Binding Options.UnlockFps, Mode=TwoWay}"
|
||||
OffContent="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsOff}"
|
||||
OnContent="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsOn}"
|
||||
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
||||
@@ -253,7 +265,7 @@
|
||||
<wsc:Setting.Description>
|
||||
<StackPanel>
|
||||
<TextBlock Text="{shcm:ResourceString Name=ViewPageLaunchGameSetFpsDescription}"/>
|
||||
<TextBlock Text="{Binding TargetFps}"/>
|
||||
<TextBlock Text="{Binding Options.TargetFps}"/>
|
||||
</StackPanel>
|
||||
</wsc:Setting.Description>
|
||||
<wsc:Setting.ActionContent>
|
||||
@@ -261,7 +273,7 @@
|
||||
Width="400"
|
||||
Maximum="360"
|
||||
Minimum="60"
|
||||
Value="{Binding TargetFps, Mode=TwoWay}"/>
|
||||
Value="{Binding Options.TargetFps, Mode=TwoWay}"/>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
</wsc:SettingsGroup>
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
namespace Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
/// <summary>
|
||||
/// 角色搭配
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class ComplexAvatarCollocation
|
||||
internal sealed class AvatarCollocationView
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色Id
|
||||
@@ -19,15 +19,15 @@ internal sealed class ComplexAvatarCollocation
|
||||
/// <summary>
|
||||
/// 角色
|
||||
/// </summary>
|
||||
public List<ComplexAvatar> Avatars { get; set; } = default!;
|
||||
public List<AvatarView> Avatars { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 武器
|
||||
/// </summary>
|
||||
public List<ComplexWeapon> Weapons { get; set; } = default!;
|
||||
public List<WeaponView> Weapons { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物套装
|
||||
/// </summary>
|
||||
public List<ComplexReliquarySet> ReliquarySets { get; set; } = default!;
|
||||
public List<ReliquarySetView> ReliquarySets { get; set; } = default!;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
|
||||
@@ -9,7 +10,7 @@ namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
/// 角色命座信息
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class ComplexAvatarConstellationInfo : ComplexAvatar
|
||||
internal sealed class AvatarConstellationInfoView : AvatarView
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的角色命座信息
|
||||
@@ -17,7 +18,7 @@ internal sealed class ComplexAvatarConstellationInfo : ComplexAvatar
|
||||
/// <param name="avatar">角色</param>
|
||||
/// <param name="rate">持有率</param>
|
||||
/// <param name="rates">命座比率</param>
|
||||
public ComplexAvatarConstellationInfo(Avatar avatar, double rate, IEnumerable<double> rates)
|
||||
public AvatarConstellationInfoView(Avatar avatar, double rate, IEnumerable<double> rates)
|
||||
: base(avatar, rate)
|
||||
{
|
||||
Rates = rates.Select(r => $"{r:P3}").ToList();
|
||||
@@ -26,5 +27,5 @@ internal sealed class ComplexAvatarConstellationInfo : ComplexAvatar
|
||||
/// <summary>
|
||||
/// 命座比率
|
||||
/// </summary>
|
||||
public List<string> Rates { get; set; }
|
||||
public List<string> Rates { get; }
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
namespace Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
/// <summary>
|
||||
/// 角色榜
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class ComplexAvatarRank
|
||||
internal sealed class AvatarRankView
|
||||
{
|
||||
/// <summary>
|
||||
/// 层数
|
||||
@@ -17,5 +17,5 @@ internal sealed class ComplexAvatarRank
|
||||
/// <summary>
|
||||
/// 排行信息
|
||||
/// </summary>
|
||||
public List<ComplexAvatar> Avatars { get; set; } = default!;
|
||||
public List<AvatarView> Avatars { get; set; } = default!;
|
||||
}
|
||||
@@ -1,24 +1,25 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Binding;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.Model.Metadata.Converter;
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
namespace Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
/// <summary>
|
||||
/// 角色
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal class ComplexAvatar : INameIconSide
|
||||
internal class AvatarView : INameIconSide
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个胡桃数据库角色
|
||||
/// </summary>
|
||||
/// <param name="avatar">元数据角色</param>
|
||||
/// <param name="rate">率</param>
|
||||
public ComplexAvatar(Avatar avatar, double rate)
|
||||
public AvatarView(Avatar avatar, double rate)
|
||||
{
|
||||
Name = avatar.Name;
|
||||
Icon = AvatarIconConverter.IconNameToUri(avatar.Icon);
|
||||
@@ -30,25 +31,25 @@ internal class ComplexAvatar : INameIconSide
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name { get; set; } = default!;
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
public Uri Icon { get; set; } = default!;
|
||||
public Uri Icon { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 侧面图标
|
||||
/// </summary>
|
||||
public Uri SideIcon { get; set; } = default!;
|
||||
public Uri SideIcon { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 星级
|
||||
/// </summary>
|
||||
public ItemQuality Quality { get; set; }
|
||||
public ItemQuality Quality { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 比率
|
||||
/// </summary>
|
||||
public string Rate { get; set; } = default!;
|
||||
public string Rate { get; }
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Service.Hutao;
|
||||
using Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
namespace Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
/// <summary>
|
||||
/// 胡桃数据库视图模型
|
||||
@@ -17,10 +16,10 @@ internal sealed class HutaoDatabaseViewModel : Abstraction.ViewModel
|
||||
{
|
||||
private readonly IHutaoCache hutaoCache;
|
||||
|
||||
private List<ComplexAvatarRank>? avatarUsageRanks;
|
||||
private List<ComplexAvatarRank>? avatarAppearanceRanks;
|
||||
private List<ComplexAvatarConstellationInfo>? avatarConstellationInfos;
|
||||
private List<ComplexTeamRank>? teamAppearances;
|
||||
private List<AvatarRankView>? avatarUsageRanks;
|
||||
private List<AvatarRankView>? avatarAppearanceRanks;
|
||||
private List<AvatarConstellationInfoView>? avatarConstellationInfos;
|
||||
private List<TeamAppearanceView>? teamAppearances;
|
||||
private Overview? overview;
|
||||
|
||||
/// <summary>
|
||||
@@ -30,41 +29,35 @@ internal sealed class HutaoDatabaseViewModel : Abstraction.ViewModel
|
||||
public HutaoDatabaseViewModel(IHutaoCache hutaoCache)
|
||||
{
|
||||
this.hutaoCache = hutaoCache;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 角色使用率
|
||||
/// </summary>
|
||||
public List<ComplexAvatarRank>? AvatarUsageRanks { get => avatarUsageRanks; set => SetProperty(ref avatarUsageRanks, value); }
|
||||
public List<AvatarRankView>? AvatarUsageRanks { get => avatarUsageRanks; set => SetProperty(ref avatarUsageRanks, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 角色上场率
|
||||
/// </summary>
|
||||
public List<ComplexAvatarRank>? AvatarAppearanceRanks { get => avatarAppearanceRanks; set => SetProperty(ref avatarAppearanceRanks, value); }
|
||||
public List<AvatarRankView>? AvatarAppearanceRanks { get => avatarAppearanceRanks; set => SetProperty(ref avatarAppearanceRanks, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 角色命座信息
|
||||
/// </summary>
|
||||
public List<ComplexAvatarConstellationInfo>? AvatarConstellationInfos { get => avatarConstellationInfos; set => SetProperty(ref avatarConstellationInfos, value); }
|
||||
public List<AvatarConstellationInfoView>? AvatarConstellationInfos { get => avatarConstellationInfos; set => SetProperty(ref avatarConstellationInfos, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 队伍出场
|
||||
/// </summary>
|
||||
public List<ComplexTeamRank>? TeamAppearances { get => teamAppearances; set => SetProperty(ref teamAppearances, value); }
|
||||
public List<TeamAppearanceView>? TeamAppearances { get => teamAppearances; set => SetProperty(ref teamAppearances, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 总览数据
|
||||
/// </summary>
|
||||
public Overview? Overview { get => overview; set => SetProperty(ref overview, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 打开界面命令
|
||||
/// </summary>
|
||||
public ICommand OpenUICommand { get; }
|
||||
|
||||
private async Task OpenUIAsync()
|
||||
/// <inheritdoc/>
|
||||
protected override async Task OpenUIAsync()
|
||||
{
|
||||
if (await hutaoCache.InitializeForDatabaseViewModelAsync().ConfigureAwait(true))
|
||||
{
|
||||
@@ -6,30 +6,30 @@ using Snap.Hutao.Model.Primitive;
|
||||
using Snap.Hutao.Web.Hutao.Model;
|
||||
using System.Text;
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
namespace Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物套装
|
||||
/// </summary>
|
||||
internal sealed class ComplexReliquarySet
|
||||
internal sealed class ReliquarySetView
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的胡桃数据库圣遗物套装
|
||||
/// </summary>
|
||||
/// <param name="reliquarySetRate">圣遗物套装率</param>
|
||||
/// <param name="idReliquarySetMap">圣遗物套装映射</param>
|
||||
public ComplexReliquarySet(ItemRate<ReliquarySets, double> reliquarySetRate, Dictionary<EquipAffixId, Metadata.Reliquary.ReliquarySet> idReliquarySetMap)
|
||||
public ReliquarySetView(ItemRate<ReliquarySets, double> reliquarySetRate, Dictionary<EquipAffixId, Model.Metadata.Reliquary.ReliquarySet> idReliquarySetMap)
|
||||
{
|
||||
ReliquarySets sets = reliquarySetRate.Item;
|
||||
|
||||
if (sets.Count >= 1)
|
||||
{
|
||||
StringBuilder nameBuilder = new();
|
||||
List<Uri> icons = new();
|
||||
List<Uri> icons = new(2);
|
||||
|
||||
foreach (ReliquarySet set in sets)
|
||||
{
|
||||
Metadata.Reliquary.ReliquarySet metaSet = idReliquarySetMap[set.EquipAffixId / 10];
|
||||
Model.Metadata.Reliquary.ReliquarySet metaSet = idReliquarySetMap[set.EquipAffixId / 10];
|
||||
|
||||
if (nameBuilder.Length != 0)
|
||||
{
|
||||
@@ -45,7 +45,7 @@ internal sealed class ComplexReliquarySet
|
||||
}
|
||||
else
|
||||
{
|
||||
Name = "无圣遗物或散件";
|
||||
Name = SH.ViewModelComplexReliquarySetViewEmptyName;
|
||||
}
|
||||
|
||||
Rate = $"{reliquarySetRate.Rate:P3}";
|
||||
@@ -5,13 +5,13 @@ using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
using Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
namespace Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
/// <summary>
|
||||
/// 队伍
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class Team : List<ComplexAvatar>
|
||||
internal sealed class Team : List<AvatarView>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的队伍
|
||||
@@ -5,20 +5,20 @@ using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
using Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
namespace Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
/// <summary>
|
||||
/// 队伍排行
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class ComplexTeamRank
|
||||
internal sealed class TeamAppearanceView
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的队伍排行
|
||||
/// </summary>
|
||||
/// <param name="teamRank">队伍排行</param>
|
||||
/// <param name="idAvatarMap">映射</param>
|
||||
public ComplexTeamRank(TeamAppearance teamRank, Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||
public TeamAppearanceView(TeamAppearance teamRank, Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||
{
|
||||
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, teamRank.Floor);
|
||||
Up = teamRank.Up.Select(teamRate => new Team(teamRate, idAvatarMap)).ToList();
|
||||
@@ -3,18 +3,18 @@
|
||||
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
namespace Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
/// <summary>
|
||||
/// 武器搭配
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class ComplexWeaponCollocation
|
||||
internal sealed class WeaponCollocationView
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色
|
||||
/// </summary>
|
||||
public List<ComplexAvatar> Avatars { get; set; } = default!;
|
||||
public List<AvatarView> Avatars { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 武器Id
|
||||
@@ -1,24 +1,25 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Binding;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata.Converter;
|
||||
using Snap.Hutao.Model.Metadata.Weapon;
|
||||
|
||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||
namespace Snap.Hutao.ViewModel.Complex;
|
||||
|
||||
/// <summary>
|
||||
/// 胡桃数据库武器
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class ComplexWeapon : INameIcon
|
||||
internal sealed class WeaponView : INameIcon
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个胡桃数据库武器
|
||||
/// </summary>
|
||||
/// <param name="weapon">元数据武器</param>
|
||||
/// <param name="rate">率</param>
|
||||
public ComplexWeapon(Weapon weapon, double rate)
|
||||
public WeaponView(Weapon weapon, double rate)
|
||||
{
|
||||
Name = weapon.Name;
|
||||
Icon = EquipIconConverter.IconNameToUri(weapon.Icon);
|
||||
@@ -2,12 +2,9 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Core.LifeCycle;
|
||||
using Snap.Hutao.Model.Binding.LaunchGame;
|
||||
@@ -21,7 +18,6 @@ using Snap.Hutao.View.Dialog;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using Windows.Graphics;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
@@ -47,13 +43,6 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
||||
private LaunchScheme? selectedScheme;
|
||||
private ObservableCollection<GameAccount>? gameAccounts;
|
||||
private GameAccount? selectedGameAccount;
|
||||
private bool isExclusive;
|
||||
private bool isFullScreen;
|
||||
private bool isBorderless;
|
||||
private int screenWidth;
|
||||
private int screenHeight;
|
||||
private bool unlockFps;
|
||||
private int targetFps;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的启动游戏视图模型
|
||||
@@ -64,9 +53,9 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
||||
gameService = serviceProvider.GetRequiredService<IGameService>();
|
||||
appDbContext = serviceProvider.GetRequiredService<AppDbContext>();
|
||||
memoryCache = serviceProvider.GetRequiredService<IMemoryCache>();
|
||||
Options = serviceProvider.GetRequiredService<LaunchOptions>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
LaunchCommand = new AsyncRelayCommand(LaunchAsync);
|
||||
DetectGameAccountCommand = new AsyncRelayCommand(DetectGameAccountAsync);
|
||||
ModifyGameAccountCommand = new AsyncRelayCommand<GameAccount>(ModifyGameAccountAsync);
|
||||
@@ -95,76 +84,9 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
||||
public GameAccount? SelectedGameAccount { get => selectedGameAccount; set => SetProperty(ref selectedGameAccount, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为独占全屏
|
||||
/// 启动选项
|
||||
/// </summary>
|
||||
public bool IsExclusive
|
||||
{
|
||||
get => isExclusive; set
|
||||
{
|
||||
if (SetProperty(ref isExclusive, value))
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
IsFullScreen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 全屏
|
||||
/// </summary>
|
||||
public bool IsFullScreen
|
||||
{
|
||||
get => isFullScreen; set
|
||||
{
|
||||
if (SetProperty(ref isFullScreen, value))
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
IsBorderless = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无边框
|
||||
/// </summary>
|
||||
public bool IsBorderless
|
||||
{
|
||||
get => isBorderless; set
|
||||
{
|
||||
if (SetProperty(ref isBorderless, value))
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
IsExclusive = false;
|
||||
IsFullScreen = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 宽度
|
||||
/// </summary>
|
||||
public int ScreenWidth { get => screenWidth; set => SetProperty(ref screenWidth, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 高度
|
||||
/// </summary>
|
||||
public int ScreenHeight { get => screenHeight; set => SetProperty(ref screenHeight, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 解锁帧率
|
||||
/// </summary>
|
||||
public bool UnlockFps { get => unlockFps; set => SetProperty(ref unlockFps, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 目标帧率
|
||||
/// </summary>
|
||||
public int TargetFps { get => targetFps; set => SetProperty(ref targetFps, value); }
|
||||
public LaunchOptions Options { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否提权
|
||||
@@ -172,11 +94,6 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
||||
[SuppressMessage("", "CA1822")]
|
||||
public bool IsElevated { get => Activation.GetElevated(); }
|
||||
|
||||
/// <summary>
|
||||
/// 打开界面命令
|
||||
/// </summary>
|
||||
public ICommand OpenUICommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 启动游戏命令
|
||||
/// </summary>
|
||||
@@ -202,7 +119,8 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
||||
/// </summary>
|
||||
public ICommand AttachGameAccountCommand { get; }
|
||||
|
||||
private async Task OpenUIAsync()
|
||||
/// <inheritdoc/>
|
||||
protected override async Task OpenUIAsync()
|
||||
{
|
||||
if (File.Exists(gameService.GetGamePathSkipLocator()))
|
||||
{
|
||||
@@ -228,9 +146,6 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
||||
SelectedGameAccount = GameAccounts.FirstOrDefault(g => g.AttachUid == uid);
|
||||
memoryCache.Remove(DesiredUid);
|
||||
}
|
||||
|
||||
// Sync from Settings
|
||||
RetiveSetting();
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -246,44 +161,6 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
private void RetiveSetting()
|
||||
{
|
||||
DbSet<SettingEntry> settings = appDbContext.Settings;
|
||||
|
||||
isFullScreen = settings.SingleOrAdd(SettingEntry.LaunchIsFullScreen, Core.StringLiterals.True).GetBoolean();
|
||||
OnPropertyChanged(nameof(IsFullScreen));
|
||||
|
||||
isBorderless = settings.SingleOrAdd(SettingEntry.LaunchIsBorderless, Core.StringLiterals.False).GetBoolean();
|
||||
OnPropertyChanged(nameof(IsBorderless));
|
||||
|
||||
RectInt32 primaryRect = DisplayArea.Primary.OuterBounds;
|
||||
|
||||
screenWidth = settings.SingleOrAdd(SettingEntry.LaunchScreenWidth, $"{primaryRect.Width}").GetInt32();
|
||||
OnPropertyChanged(nameof(ScreenWidth));
|
||||
|
||||
screenHeight = settings.SingleOrAdd(SettingEntry.LaunchScreenHeight, $"{primaryRect.Height}").GetInt32();
|
||||
OnPropertyChanged(nameof(ScreenHeight));
|
||||
|
||||
unlockFps = settings.SingleOrAdd(SettingEntry.LaunchUnlockFps, Core.StringLiterals.False).GetBoolean();
|
||||
OnPropertyChanged(nameof(UnlockFps));
|
||||
|
||||
targetFps = settings.SingleOrAdd(SettingEntry.LaunchTargetFps, "60").GetInt32();
|
||||
OnPropertyChanged(nameof(TargetFps));
|
||||
}
|
||||
|
||||
private void SaveSetting()
|
||||
{
|
||||
DbSet<SettingEntry> settings = appDbContext.Settings;
|
||||
settings.SingleOrAdd(SettingEntry.LaunchIsExclusive, Core.StringLiterals.False).SetBoolean(IsExclusive);
|
||||
settings.SingleOrAdd(SettingEntry.LaunchIsFullScreen, Core.StringLiterals.False).SetBoolean(IsFullScreen);
|
||||
settings.SingleOrAdd(SettingEntry.LaunchIsBorderless, Core.StringLiterals.False).SetBoolean(IsBorderless);
|
||||
settings.SingleOrAdd(SettingEntry.LaunchScreenWidth, "1920").SetInt32(ScreenWidth);
|
||||
settings.SingleOrAdd(SettingEntry.LaunchScreenHeight, "1080").SetInt32(ScreenHeight);
|
||||
settings.SingleOrAdd(SettingEntry.LaunchUnlockFps, Core.StringLiterals.False).SetBoolean(UnlockFps);
|
||||
settings.SingleOrAdd(SettingEntry.LaunchTargetFps, "60").SetInt32(TargetFps);
|
||||
appDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
private async Task LaunchAsync()
|
||||
{
|
||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
@@ -322,10 +199,7 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
SaveSetting();
|
||||
|
||||
LaunchConfiguration configuration = new(IsExclusive, IsFullScreen, IsBorderless, ScreenWidth, ScreenHeight, IsElevated && UnlockFps, TargetFps);
|
||||
await gameService.LaunchAsync(configuration).ConfigureAwait(false);
|
||||
await gameService.LaunchAsync(Options).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -46,10 +46,10 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
|
||||
|
||||
private readonly List<NameValue<string>> cultures = new()
|
||||
{
|
||||
ToNameValue(CultureInfo.CreateSpecificCulture("zh-CN")),
|
||||
ToNameValue(CultureInfo.CreateSpecificCulture("zh-TW")),
|
||||
ToNameValue(CultureInfo.CreateSpecificCulture("en-US")),
|
||||
ToNameValue(CultureInfo.CreateSpecificCulture("ko-KR")),
|
||||
ToNameValue(CultureInfo.GetCultureInfo("zh-Hans")),
|
||||
ToNameValue(CultureInfo.GetCultureInfo("zh-Hant")),
|
||||
ToNameValue(CultureInfo.GetCultureInfo("en")),
|
||||
ToNameValue(CultureInfo.GetCultureInfo("ko")),
|
||||
};
|
||||
|
||||
private bool isEmptyHistoryWishVisible;
|
||||
@@ -102,7 +102,7 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Webview2 版本
|
||||
/// WebView2 版本
|
||||
/// </summary>
|
||||
[SuppressMessage("", "CA1822")]
|
||||
public string WebView2Version
|
||||
@@ -226,6 +226,12 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
|
||||
/// </summary>
|
||||
public ICommand ResetStaticResourceCommand { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task OpenUIAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static NameValue<string> ToNameValue(CultureInfo info)
|
||||
{
|
||||
return new(info.NativeName, info.Name);
|
||||
|
||||
@@ -52,7 +52,6 @@ internal sealed class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecip
|
||||
userService = serviceProvider.GetRequiredService<IUserService>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
RefreshCommand = new AsyncRelayCommand(RefreshAsync);
|
||||
UploadSpiralAbyssRecordCommand = new AsyncRelayCommand(UploadSpiralAbyssRecordAsync);
|
||||
|
||||
@@ -86,11 +85,6 @@ internal sealed class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecip
|
||||
/// </summary>
|
||||
public SpiralAbyssView? SpiralAbyssView { get => spiralAbyssView; set => SetProperty(ref spiralAbyssView, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 打开界面命令
|
||||
/// </summary>
|
||||
public ICommand OpenUICommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 刷新界面命令
|
||||
/// </summary>
|
||||
@@ -114,7 +108,8 @@ internal sealed class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecip
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OpenUIAsync()
|
||||
/// <inheritdoc/>
|
||||
protected override async Task OpenUIAsync()
|
||||
{
|
||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||
{
|
||||
|
||||
@@ -53,6 +53,12 @@ internal sealed class TestViewModel : Abstraction.ViewModel
|
||||
/// </summary>
|
||||
public ICommand RestartAppCommand { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task OpenUIAsync()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task ShowCommunityGameRecordDialogAsync()
|
||||
{
|
||||
// ContentDialog must be created by main thread.
|
||||
|
||||
@@ -20,6 +20,7 @@ using Snap.Hutao.Service.Hutao;
|
||||
using Snap.Hutao.Service.Metadata;
|
||||
using Snap.Hutao.Service.User;
|
||||
using Snap.Hutao.View.Dialog;
|
||||
using Snap.Hutao.ViewModel.Complex;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using System.Collections.Immutable;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -59,7 +60,6 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
hutaoCache = serviceProvider.GetRequiredService<IHutaoCache>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
CultivateCommand = new AsyncRelayCommand<Avatar>(CultivateAsync);
|
||||
FilterCommand = new RelayCommand<string>(ApplyFilter);
|
||||
}
|
||||
@@ -93,11 +93,6 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
/// </summary>
|
||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 打开页面命令
|
||||
/// </summary>
|
||||
public ICommand OpenUICommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 养成命令
|
||||
/// </summary>
|
||||
@@ -108,7 +103,8 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
/// </summary>
|
||||
public ICommand FilterCommand { get; }
|
||||
|
||||
private async Task OpenUIAsync()
|
||||
/// <inheritdoc/>
|
||||
protected override async Task OpenUIAsync()
|
||||
{
|
||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||
{
|
||||
@@ -134,7 +130,7 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
{
|
||||
if (await hutaoCache.InitializeForWikiAvatarViewModelAsync().ConfigureAwait(false))
|
||||
{
|
||||
Dictionary<AvatarId, ComplexAvatarCollocation> idCollocations = hutaoCache.AvatarCollocations!.ToDictionary(a => a.AvatarId);
|
||||
Dictionary<AvatarId, AvatarCollocationView> idCollocations = hutaoCache.AvatarCollocations!.ToDictionary(a => a.AvatarId);
|
||||
|
||||
foreach (Avatar avatar in avatars)
|
||||
{
|
||||
|
||||
@@ -1,31 +1,15 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.WinUI.UI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Snap.Hutao.Model.Binding.BaseValue;
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Model.Entity.Primitive;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Intrinsic.Immutable;
|
||||
using Snap.Hutao.Model.Metadata.Item;
|
||||
using Snap.Hutao.Model.Metadata.Monster;
|
||||
using Snap.Hutao.Model.Metadata.Weapon;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Service.Cultivation;
|
||||
using Snap.Hutao.Service.Hutao;
|
||||
using Snap.Hutao.Service.Metadata;
|
||||
using Snap.Hutao.Service.User;
|
||||
using Snap.Hutao.View.Dialog;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using System.Collections.Immutable;
|
||||
using System.Runtime.InteropServices;
|
||||
using CalcAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
|
||||
using CalcClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient;
|
||||
using CalcConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Consumption;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
@@ -35,16 +19,13 @@ namespace Snap.Hutao.ViewModel;
|
||||
[Injection(InjectAs.Scoped)]
|
||||
internal class WikiMonsterViewModel : Abstraction.ViewModel
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly IMetadataService metadataService;
|
||||
private readonly IHutaoCache hutaoCache;
|
||||
|
||||
private AdvancedCollectionView? monsters;
|
||||
private Monster? selected;
|
||||
private string? filterText;
|
||||
private BaseValueInfo? baseValueInfo;
|
||||
private Dictionary<int, Dictionary<GrowCurveType, float>>? levelMonsterCurveMap;
|
||||
private Dictionary<MaterialId, Material>? idMaterialMap;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的怪物资料视图模型
|
||||
@@ -53,10 +34,6 @@ internal class WikiMonsterViewModel : Abstraction.ViewModel
|
||||
public WikiMonsterViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
metadataService = serviceProvider.GetRequiredService<IMetadataService>();
|
||||
hutaoCache = serviceProvider.GetRequiredService<IHutaoCache>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -88,12 +65,8 @@ internal class WikiMonsterViewModel : Abstraction.ViewModel
|
||||
/// </summary>
|
||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 打开界面命令
|
||||
/// </summary>
|
||||
public ICommand OpenUICommand { get; }
|
||||
|
||||
private async Task OpenUIAsync()
|
||||
/// <inheritdoc/>
|
||||
protected override async Task OpenUIAsync()
|
||||
{
|
||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@ using CommunityToolkit.WinUI.UI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Snap.Hutao.Model.Binding.BaseValue;
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Model.Entity.Primitive;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Intrinsic.Immutable;
|
||||
@@ -19,6 +18,7 @@ using Snap.Hutao.Service.Hutao;
|
||||
using Snap.Hutao.Service.Metadata;
|
||||
using Snap.Hutao.Service.User;
|
||||
using Snap.Hutao.View.Dialog;
|
||||
using Snap.Hutao.ViewModel.Complex;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using System.Collections.Immutable;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -61,7 +61,6 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
hutaoCache = serviceProvider.GetRequiredService<IHutaoCache>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
CultivateCommand = new AsyncRelayCommand<Weapon>(CultivateAsync);
|
||||
FilterCommand = new RelayCommand<string>(ApplyFilter);
|
||||
}
|
||||
@@ -95,11 +94,6 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
/// </summary>
|
||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 打开界面命令
|
||||
/// </summary>
|
||||
public ICommand OpenUICommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 养成命令
|
||||
/// </summary>
|
||||
@@ -110,7 +104,8 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
/// </summary>
|
||||
public ICommand FilterCommand { get; }
|
||||
|
||||
private async Task OpenUIAsync()
|
||||
/// <inheritdoc/>
|
||||
protected override async Task OpenUIAsync()
|
||||
{
|
||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||
{
|
||||
@@ -137,7 +132,7 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
{
|
||||
if (await hutaoCache.InitializeForWikiWeaponViewModelAsync().ConfigureAwait(false))
|
||||
{
|
||||
Dictionary<WeaponId, ComplexWeaponCollocation> idCollocations = hutaoCache.WeaponCollocations!.ToDictionary(a => a.WeaponId);
|
||||
Dictionary<WeaponId, WeaponCollocationView> idCollocations = hutaoCache.WeaponCollocations!.ToDictionary(a => a.WeaponId);
|
||||
weapons.ForEach(w => w.Collocation = idCollocations.GetValueOrDefault(w.Id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Buffers.Binary;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Windows.Graphics;
|
||||
using Windows.Win32.Graphics.Gdi;
|
||||
using Windows.Win32.System.Diagnostics.ToolHelp;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user