This commit is contained in:
DismissedLight
2023-04-04 16:53:01 +08:00
parent 35e7aaef4e
commit 79118cdb4d
13 changed files with 356 additions and 418 deletions

View File

@@ -14,8 +14,8 @@ public class DependencyInjectionTest
.AddSingleton<IService, ServiceB>() .AddSingleton<IService, ServiceB>()
.BuildServiceProvider(); .BuildServiceProvider();
Assert.IsNotNull(services.GetService<ServiceA>()); Assert.IsNull(services.GetService<ServiceA>());
Assert.IsNotNull(services.GetService<ServiceB>()); Assert.IsNull(services.GetService<ServiceB>());
} }
private interface IService private interface IService

View File

@@ -29,8 +29,9 @@
<!-- Page Transparent Background --> <!-- Page Transparent Background -->
<StaticResource x:Key="ApplicationPageBackgroundThemeBrush" ResourceKey="ControlFillColorTransparentBrush"/> <StaticResource x:Key="ApplicationPageBackgroundThemeBrush" ResourceKey="ControlFillColorTransparentBrush"/>
<!-- InfoBar Resource --> <!-- InfoBar Resource -->
<Thickness x:Key="InfoBarIconMargin">6,16,16,16</Thickness> <Thickness x:Key="InfoBarIconMargin">19,16,19,16</Thickness>
<Thickness x:Key="InfoBarContentRootPadding">16,0,0,0</Thickness> <Thickness x:Key="InfoBarContentRootPadding">0,0,0,0</Thickness>
<x:Double x:Key="InfoBarIconFontSize">20</x:Double>
<!-- Pivot Resource --> <!-- Pivot Resource -->
<x:Double x:Key="PivotHeaderItemFontSize">16</x:Double> <x:Double x:Key="PivotHeaderItemFontSize">16</x:Double>
<Thickness x:Key="PivotHeaderItemMargin">16,0,0,0</Thickness> <Thickness x:Key="PivotHeaderItemMargin">16,0,0,0</Thickness>

View File

@@ -3624,6 +3624,15 @@ namespace Snap.Hutao.Resource.Localization {
} }
} }
/// <summary>
/// 查找类似 至少需要 8 个字符 的本地化字符串。
/// </summary>
internal static string ViewPageHutaoPassportPasswordRequirementHint {
get {
return ResourceManager.GetString("ViewPageHutaoPassportPasswordRequirementHint", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 注册 的本地化字符串。 /// 查找类似 注册 的本地化字符串。
/// </summary> /// </summary>

View File

@@ -1842,4 +1842,7 @@
<data name="ViewPageHutaoPassportVerifyCodeHint" xml:space="preserve"> <data name="ViewPageHutaoPassportVerifyCodeHint" xml:space="preserve">
<value>请输入验证码</value> <value>请输入验证码</value>
</data> </data>
<data name="ViewPageHutaoPassportPasswordRequirementHint" xml:space="preserve">
<value>至少需要 8 个字符</value>
</data>
</root> </root>

View File

@@ -0,0 +1,250 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.Extensions.Options;
using Snap.Hutao.Core.Database;
using Snap.Hutao.Model.Entity.Database;
namespace Snap.Hutao.Service.Abstraction;
/// <summary>
/// 数据库存储选项的设置
/// </summary>
/// <typeparam name="TOptions">选项类型自身</typeparam>
internal abstract class DbStoreOptions : ObservableObject, IOptions<DbStoreOptions>
{
private readonly IServiceScopeFactory serviceScopeFactory;
/// <summary>
/// 构造一个新的数据库存储选项的设置
/// </summary>
/// <param name="serviceScopeFactory">服务工厂</param>
public DbStoreOptions(IServiceScopeFactory serviceScopeFactory)
{
this.serviceScopeFactory = serviceScopeFactory;
}
/// <inheritdoc/>
public DbStoreOptions Value { get => this; }
/// <summary>
/// 从数据库中获取字符串数据
/// </summary>
/// <param name="storage">存储字段</param>
/// <param name="key">键</param>
/// <param name="defaultValue">默认值</param>
/// <returns>值</returns>
protected string GetOption(ref string? storage, string key, string defaultValue = "")
{
if (storage == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
storage = appDbContext.Settings.SingleOrDefault(e => e.Key == key)?.Value ?? defaultValue;
}
}
return storage;
}
/// <summary>
/// 从数据库中获取bool数据
/// </summary>
/// <param name="storage">存储字段</param>
/// <param name="key">键</param>
/// <param name="defaultValue">默认值</param>
/// <returns>值</returns>
protected bool GetOption(ref bool? storage, string key, bool defaultValue = false)
{
if (storage == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == key)?.Value;
storage = value == null ? defaultValue : bool.Parse(value);
}
}
return storage.Value;
}
/// <summary>
/// 从数据库中获取int数据
/// </summary>
/// <param name="storage">存储字段</param>
/// <param name="key">键</param>
/// <param name="defaultValue">默认值</param>
/// <returns>值</returns>
protected int GetOption(ref int? storage, string key, int defaultValue = 0)
{
if (storage == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == key)?.Value;
storage = value == null ? defaultValue : int.Parse(value);
}
}
return storage.Value;
}
/// <summary>
/// 从数据库中获取任何类型的数据
/// </summary>
/// <typeparam name="T">数据的类型</typeparam>
/// <param name="storage">存储字段</param>
/// <param name="key">键</param>
/// <param name="deserializer">反序列化器</param>
/// <param name="defaultValue">默认值</param>
/// <returns>值</returns>
protected T GetOption<T>(ref T? storage, string key, Func<string, T> deserializer, T defaultValue)
where T : class
{
if (storage == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == key)?.Value;
storage = value == null ? defaultValue : deserializer(value);
}
}
return storage;
}
/// <summary>
/// 从数据库中获取任何类型的数据
/// </summary>
/// <typeparam name="T">数据的类型</typeparam>
/// <param name="storage">存储字段</param>
/// <param name="key">键</param>
/// <param name="deserializer">反序列化器</param>
/// <param name="defaultValue">默认值</param>
/// <returns>值</returns>
protected T GetOption<T>(ref T? storage, string key, Func<string, T> deserializer, T defaultValue)
where T : struct
{
if (storage == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == key)?.Value;
storage = value == null ? defaultValue : deserializer(value);
}
}
return storage.Value;
}
/// <summary>
/// 将值存入数据库
/// </summary>
/// <param name="storage">存储字段</param>
/// <param name="key">键</param>
/// <param name="value">值</param>
protected void SetOption(ref string? storage, string key, string value)
{
if (SetProperty(ref storage, value))
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == key);
appDbContext.Settings.AddAndSave(new(key, value));
}
}
}
/// <summary>
/// 将值存入数据库
/// </summary>
/// <param name="storage">存储字段</param>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <returns>是否设置了值</returns>
protected bool SetOption(ref bool? storage, string key, bool value)
{
bool set = SetProperty(ref storage, value);
if (set)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == key);
appDbContext.Settings.AddAndSave(new(key, value.ToString()));
}
}
return set;
}
/// <summary>
/// 将值存入数据库
/// </summary>
/// <param name="storage">存储字段</param>
/// <param name="key">键</param>
/// <param name="value">值</param>
protected void SetOption(ref int? storage, string key, int value)
{
if (SetProperty(ref storage, value))
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == key);
appDbContext.Settings.AddAndSave(new(key, value.ToString()));
}
}
}
/// <summary>
/// 将值存入数据库
/// </summary>
/// <typeparam name="T">数据的类型</typeparam>
/// <param name="storage">存储字段</param>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="serializer">序列化器</param>
protected void SetOption<T>(ref T? storage, string key, T value, Func<T, string> serializer)
where T : class
{
if (SetProperty(ref storage, value))
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == key);
appDbContext.Settings.AddAndSave(new(key, serializer(value)));
}
}
}
/// <summary>
/// 将值存入数据库
/// </summary>
/// <typeparam name="T">数据的类型</typeparam>
/// <param name="storage">存储字段</param>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="serializer">序列化器</param>
protected void SetOption<T>(ref T? storage, string key, T value, Func<T, string> serializer)
where T : struct
{
if (SetProperty(ref storage, value))
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == key);
appDbContext.Settings.AddAndSave(new(key, serializer(value)));
}
}
}
}

View File

@@ -1,12 +1,8 @@
// 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.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Options;
using Snap.Hutao.Core.Database;
using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.Entity.Database; using Snap.Hutao.Service.Abstraction;
using System.Globalization; using System.Globalization;
namespace Snap.Hutao.Service; namespace Snap.Hutao.Service;
@@ -15,10 +11,8 @@ namespace Snap.Hutao.Service;
/// 应用程序选项 /// 应用程序选项
/// </summary> /// </summary>
[Injection(InjectAs.Singleton)] [Injection(InjectAs.Singleton)]
internal sealed class AppOptions : ObservableObject, IOptions<AppOptions> internal sealed class AppOptions : DbStoreOptions
{ {
private readonly IServiceScopeFactory serviceScopeFactory;
private string? gamePath; private string? gamePath;
private bool? isEmptyHistoryWishVisible; private bool? isEmptyHistoryWishVisible;
private Core.Windowing.BackdropType? backdropType; private Core.Windowing.BackdropType? backdropType;
@@ -30,8 +24,8 @@ internal sealed class AppOptions : ObservableObject, IOptions<AppOptions>
/// </summary> /// </summary>
/// <param name="serviceScopeFactory">服务范围工厂</param> /// <param name="serviceScopeFactory">服务范围工厂</param>
public AppOptions(IServiceScopeFactory serviceScopeFactory) public AppOptions(IServiceScopeFactory serviceScopeFactory)
: base(serviceScopeFactory)
{ {
this.serviceScopeFactory = serviceScopeFactory;
} }
/// <summary> /// <summary>
@@ -39,32 +33,8 @@ internal sealed class AppOptions : ObservableObject, IOptions<AppOptions>
/// </summary> /// </summary>
public string GamePath public string GamePath
{ {
get get => GetOption(ref gamePath, SettingEntry.GamePath);
{ set => SetOption(ref gamePath, SettingEntry.GamePath, value);
if (gamePath == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
gamePath = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.GamePath)?.Value ?? string.Empty;
}
}
return gamePath;
}
set
{
if (SetProperty(ref gamePath, value))
{
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>
@@ -72,33 +42,8 @@ internal sealed class AppOptions : ObservableObject, IOptions<AppOptions>
/// </summary> /// </summary>
public bool IsEmptyHistoryWishVisible public bool IsEmptyHistoryWishVisible
{ {
get get => GetOption(ref isEmptyHistoryWishVisible, SettingEntry.IsEmptyHistoryWishVisible);
{ set => SetOption(ref isEmptyHistoryWishVisible, SettingEntry.IsEmptyHistoryWishVisible, value);
if (isEmptyHistoryWishVisible == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.IsEmptyHistoryWishVisible)?.Value;
isEmptyHistoryWishVisible = value != null && bool.Parse(value);
}
}
return isEmptyHistoryWishVisible.Value;
}
set
{
if (SetProperty(ref isEmptyHistoryWishVisible, value))
{
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> /// <summary>
@@ -106,35 +51,8 @@ internal sealed class AppOptions : ObservableObject, IOptions<AppOptions>
/// </summary> /// </summary>
public Core.Windowing.BackdropType BackdropType public Core.Windowing.BackdropType BackdropType
{ {
get get => GetOption(ref backdropType, SettingEntry.SystemBackdropType, Enum.Parse<Core.Windowing.BackdropType>, Core.Windowing.BackdropType.Mica);
{ set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, value => value.ToString());
if (backdropType == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.SystemBackdropType)?.Value;
backdropType = Enum.Parse<Core.Windowing.BackdropType>(value ?? nameof(Core.Windowing.BackdropType.Mica));
}
}
return backdropType.Value;
}
set
{
if (SetProperty(ref backdropType, value))
{
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()));
scope.ServiceProvider.GetRequiredService<IMessenger>().Send(new Message.BackdropTypeChangedMessage(value));
}
}
}
} }
/// <summary> /// <summary>
@@ -142,33 +60,8 @@ internal sealed class AppOptions : ObservableObject, IOptions<AppOptions>
/// </summary> /// </summary>
public CultureInfo CurrentCulture public CultureInfo CurrentCulture
{ {
get get => GetOption(ref currentCulture, SettingEntry.Culture, CultureInfo.GetCultureInfo, CultureInfo.CurrentCulture);
{ set => SetOption(ref currentCulture, SettingEntry.Culture, value, value => value.Name);
if (currentCulture == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.Culture)?.Value;
currentCulture = value != null ? CultureInfo.GetCultureInfo(value) : CultureInfo.CurrentCulture;
}
}
return currentCulture;
}
set
{
if (SetProperty(ref currentCulture, value))
{
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));
}
}
}
} }
/// <summary> /// <summary>
@@ -176,35 +69,7 @@ internal sealed class AppOptions : ObservableObject, IOptions<AppOptions>
/// </summary> /// </summary>
public bool IsAdvancedLaunchOptionsEnabled public bool IsAdvancedLaunchOptionsEnabled
{ {
get get => GetOption(ref isAdvancedLaunchOptionsEnabled, SettingEntry.IsAdvancedLaunchOptionsEnabled);
{ set => SetOption(ref isAdvancedLaunchOptionsEnabled, SettingEntry.IsAdvancedLaunchOptionsEnabled, value);
if (isAdvancedLaunchOptionsEnabled == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.IsAdvancedLaunchOptionsEnabled)?.Value;
isAdvancedLaunchOptionsEnabled = value != null && bool.Parse(value);
}
}
return isAdvancedLaunchOptionsEnabled.Value;
}
set
{
if (SetProperty(ref isAdvancedLaunchOptionsEnabled, value))
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.IsAdvancedLaunchOptionsEnabled);
appDbContext.Settings.AddAndSave(new(SettingEntry.IsAdvancedLaunchOptionsEnabled, value.ToString()));
}
}
}
} }
/// <inheritdoc/>
public AppOptions Value { get => this; }
} }

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Service.Abstraction;
namespace Snap.Hutao.Service.DailyNote;
/// <summary>
/// 实时便笺选项
/// </summary>
[Injection(InjectAs.Singleton)]
internal sealed class DailyNoteOptions : DbStoreOptions
{
/// <summary>
/// 构造一个新的实时便笺选项
/// </summary>
/// <param name="serviceScopeFactory">服务范围工厂</param>
public DailyNoteOptions(IServiceScopeFactory serviceScopeFactory)
: base(serviceScopeFactory)
{
}
}

View File

@@ -1,13 +1,10 @@
// 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.Mvvm.ComponentModel;
using Microsoft.Extensions.Options;
using Microsoft.UI.Windowing; using Microsoft.UI.Windowing;
using Snap.Hutao.Core.Database;
using Snap.Hutao.Model; using Snap.Hutao.Model;
using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.Entity.Database; using Snap.Hutao.Service.Abstraction;
using Windows.Graphics; using Windows.Graphics;
using Windows.Win32.Foundation; using Windows.Win32.Foundation;
using Windows.Win32.Graphics.Gdi; using Windows.Win32.Graphics.Gdi;
@@ -19,9 +16,8 @@ namespace Snap.Hutao.Service.Game;
/// 启动游戏选项 /// 启动游戏选项
/// </summary> /// </summary>
[Injection(InjectAs.Singleton)] [Injection(InjectAs.Singleton)]
internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions> internal sealed class LaunchOptions : DbStoreOptions
{ {
private readonly IServiceScopeFactory serviceScopeFactory;
private readonly int primaryScreenWidth; private readonly int primaryScreenWidth;
private readonly int primaryScreenHeight; private readonly int primaryScreenHeight;
private readonly int primaryScreenFps; private readonly int primaryScreenFps;
@@ -41,8 +37,8 @@ internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
/// </summary> /// </summary>
/// <param name="serviceScopeFactory">服务范围工厂</param> /// <param name="serviceScopeFactory">服务范围工厂</param>
public LaunchOptions(IServiceScopeFactory serviceScopeFactory) public LaunchOptions(IServiceScopeFactory serviceScopeFactory)
: base(serviceScopeFactory)
{ {
this.serviceScopeFactory = serviceScopeFactory;
RectInt32 primaryRect = DisplayArea.Primary.OuterBounds; RectInt32 primaryRect = DisplayArea.Primary.OuterBounds;
primaryScreenWidth = primaryRect.Width; primaryScreenWidth = primaryRect.Width;
primaryScreenHeight = primaryRect.Height; primaryScreenHeight = primaryRect.Height;
@@ -64,36 +60,12 @@ internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
/// </summary> /// </summary>
public bool IsFullScreen public bool IsFullScreen
{ {
get get => GetOption(ref isFullScreen, SettingEntry.LaunchIsFullScreen);
{
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 set
{ {
if (SetProperty(ref isFullScreen, value)) if (SetOption(ref isFullScreen, SettingEntry.LaunchIsFullScreen, value) && value)
{ {
if (value) IsBorderless = false;
{
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()));
}
} }
} }
} }
@@ -103,37 +75,13 @@ internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
/// </summary> /// </summary>
public bool IsBorderless public bool IsBorderless
{ {
get get => GetOption(ref isBorderless, SettingEntry.LaunchIsBorderless);
{
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 set
{ {
if (SetProperty(ref isBorderless, value)) if (SetOption(ref isBorderless, SettingEntry.LaunchIsBorderless, value) && value)
{ {
if (value) IsExclusive = false;
{ IsFullScreen = false;
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()));
}
} }
} }
} }
@@ -143,36 +91,12 @@ internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
/// </summary> /// </summary>
public bool IsExclusive public bool IsExclusive
{ {
get get => GetOption(ref isExclusive, SettingEntry.LaunchIsExclusive);
{
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 set
{ {
if (SetProperty(ref isExclusive, value)) if (SetOption(ref isExclusive, SettingEntry.LaunchIsExclusive, value) && value)
{ {
if (value) IsFullScreen = true;
{
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()));
}
} }
} }
} }
@@ -182,33 +106,8 @@ internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
/// </summary> /// </summary>
public int ScreenWidth public int ScreenWidth
{ {
get get => GetOption(ref screenWidth, SettingEntry.LaunchScreenWidth, primaryScreenWidth);
{ set => SetOption(ref screenWidth, SettingEntry.LaunchScreenWidth, value);
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>
@@ -216,33 +115,8 @@ internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
/// </summary> /// </summary>
public int ScreenHeight public int ScreenHeight
{ {
get get => GetOption(ref screenHeight, SettingEntry.LaunchScreenHeight, primaryScreenHeight);
{ set => SetOption(ref screenHeight, SettingEntry.LaunchScreenHeight, value);
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>
@@ -250,33 +124,8 @@ internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
/// </summary> /// </summary>
public bool UnlockFps public bool UnlockFps
{ {
get get => GetOption(ref unlockFps, SettingEntry.LaunchUnlockFps);
{ set => SetOption(ref unlockFps, SettingEntry.LaunchUnlockFps, value);
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>
@@ -284,33 +133,8 @@ internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
/// </summary> /// </summary>
public int TargetFps public int TargetFps
{ {
get get => GetOption(ref targetFps, SettingEntry.LaunchTargetFps, primaryScreenFps);
{ set => SetOption(ref targetFps, SettingEntry.LaunchTargetFps, value);
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>
@@ -323,77 +147,19 @@ internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
/// </summary> /// </summary>
public NameValue<int> Monitor public NameValue<int> Monitor
{ {
get get => GetOption(ref monitor, SettingEntry.LaunchMonitor, index => Monitors[int.Parse(index) - 1], Monitors[0]);
{ set => SetOption(ref monitor, SettingEntry.LaunchMonitor, value, selected => selected.Value.ToString());
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))
{
if (monitor != null)
{
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()));
}
}
}
}
} }
/// <summary> /// <summary>
/// 多启动原神 /// 多启动原神
/// </summary> /// </summary>
public bool MultipleInstances public bool MultipleInstances
{ {
get get => GetOption(ref multipleInstances, SettingEntry.MultipleInstances);
{ set => SetOption(ref multipleInstances, SettingEntry.MultipleInstances, value);
if (multipleInstances == null)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.MultipleInstances)?.Value;
multipleInstances = value != null && bool.Parse(value);
}
}
return multipleInstances.Value;
}
set
{
if (SetProperty(ref multipleInstances, value))
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.MultipleInstances);
appDbContext.Settings.AddAndSave(new(SettingEntry.MultipleInstances, value.ToString()));
}
}
}
} }
/// <inheritdoc/>
public LaunchOptions Value { get => this; }
private static void InitializeScreenFps(out int fps) private static void InitializeScreenFps(out int fps)
{ {
HDC hDC = GetDC(HWND.Null); HDC hDC = GetDC(HWND.Null);

View File

@@ -60,6 +60,11 @@
IsEnabled="{Binding VerifyCode, Converter={StaticResource StringBoolConverter}}" IsEnabled="{Binding VerifyCode, Converter={StaticResource StringBoolConverter}}"
Password="{Binding Password, Mode=TwoWay}" Password="{Binding Password, Mode=TwoWay}"
PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/> PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/>
<TextBlock
Margin="0,4,0,0"
Opacity="0.7"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordRequirementHint}"/>
<Button <Button
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
@@ -89,6 +94,11 @@
IsEnabled="{Binding VerifyCode, Converter={StaticResource StringBoolConverter}}" IsEnabled="{Binding VerifyCode, Converter={StaticResource StringBoolConverter}}"
Password="{Binding Password, Mode=TwoWay}" Password="{Binding Password, Mode=TwoWay}"
PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/> PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/>
<TextBlock
Margin="0,4,0,0"
Opacity="0.7"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordRequirementHint}"/>
<Button <Button
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"

View File

@@ -47,7 +47,7 @@ internal readonly struct PlayerUid
{ {
return uid[0] switch return uid[0] switch
{ {
>= '1' and <= '4' => false, >= '1' and <= '5' => false,
_ => true, _ => true,
}; };
} }
@@ -62,8 +62,10 @@ internal readonly struct PlayerUid
{ {
return first switch return first switch
{ {
// CN
>= '1' and <= '4' => "cn_gf01", // 国服 >= '1' and <= '4' => "cn_gf01", // 国服
'5' => "cn_qd01", // 渠道 '5' => "cn_qd01", // 渠道
// OS
'6' => "os_usa", // 美服 '6' => "os_usa", // 美服
'7' => "os_euro", // 欧服 '7' => "os_euro", // 欧服
'8' => "os_asia", // 亚服 '8' => "os_asia", // 亚服

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license. // Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Service.Hutao;
using Snap.Hutao.ViewModel.User; using Snap.Hutao.ViewModel.User;
using Snap.Hutao.Web.Hoyolab; using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord; using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
@@ -205,7 +206,9 @@ internal sealed class HomaSpiralAbyssClient
if (spiralAbyssResponse.IsOk()) if (spiralAbyssResponse.IsOk())
{ {
return new(userAndUid.Uid.Value, charactersResponse.Data.Avatars, spiralAbyssResponse.Data); HutaoUserOptions options = serviceProvider.GetRequiredService<HutaoUserOptions>();
string? userName = options.Token == null ? null : options.UserName;
return new(userAndUid.Uid.Value, charactersResponse.Data.Avatars, spiralAbyssResponse.Data, userName);
} }
} }
} }

View File

@@ -18,12 +18,13 @@ internal sealed class SimpleRecord
/// <param name="uid">uid</param> /// <param name="uid">uid</param>
/// <param name="characters">详细的角色信息</param> /// <param name="characters">详细的角色信息</param>
/// <param name="spiralAbyss">深渊信息</param> /// <param name="spiralAbyss">深渊信息</param>
public SimpleRecord(string uid, List<Character> characters, SpiralAbyss spiralAbyss) public SimpleRecord(string uid, List<Character> characters, SpiralAbyss spiralAbyss, string? reservedUserName)
{ {
Uid = uid; Uid = uid;
Identity = "Snap Hutao"; // hardcoded Identity name Identity = "Snap Hutao"; // hardcoded Identity name
SpiralAbyss = new(spiralAbyss); SpiralAbyss = new(spiralAbyss);
Avatars = characters.Select(a => new SimpleAvatar(a)); Avatars = characters.Select(a => new SimpleAvatar(a));
ReservedUserName = reservedUserName;
} }
/// <summary> /// <summary>
@@ -36,6 +37,12 @@ internal sealed class SimpleRecord
/// </summary> /// </summary>
public string Identity { get; set; } = default!; public string Identity { get; set; } = default!;
/// <summary>
/// 保留属性
/// 用户名称
/// </summary>
public string? ReservedUserName { get; set; }
/// <summary> /// <summary>
/// 深境螺旋 /// 深境螺旋
/// </summary> /// </summary>

View File

@@ -49,7 +49,7 @@ internal class Response
public static Response DefaultIfNull(Response? response, [CallerMemberName] string callerName = default!) public static Response DefaultIfNull(Response? response, [CallerMemberName] string callerName = default!)
{ {
// 0x26F19335 is a magic number that hashed from "Snap.Hutao" // 0x26F19335 is a magic number that hashed from "Snap.Hutao"
return response ?? new(0x26F19335, $"[{callerName}] 中的请求异常"); return response ?? new(0x26F19335, $"[{callerName}] 中的网络请求异常,请稍后再试");
} }
/// <summary> /// <summary>
@@ -62,7 +62,7 @@ internal class Response
public static Response<TData> DefaultIfNull<TData>(Response<TData>? response, [CallerMemberName] string callerName = default!) public static Response<TData> DefaultIfNull<TData>(Response<TData>? response, [CallerMemberName] string callerName = default!)
{ {
// 0x26F19335 is a magic number that hashed from "Snap.Hutao" // 0x26F19335 is a magic number that hashed from "Snap.Hutao"
return response ?? new(0x26F19335, $"[{callerName}] 中的 [{typeof(TData).Name}] 请求异常", default); return response ?? new(0x26F19335, $"[{callerName}] 中的 [{typeof(TData).Name}] 网络请求异常,请稍后再试", default);
} }
/// <summary> /// <summary>
@@ -84,7 +84,7 @@ internal class Response
} }
else else
{ {
return new(0x26F19335, $"[{callerName}] 中的 [{typeof(TData).Name}] 请求异常", default); return new(0x26F19335, $"[{callerName}] 中的 [{typeof(TData).Name}] 网络请求异常,请稍后再试", default);
} }
} }