From 71fcbc367c2b76e4e44a5c55cfb1c77ccc3ba88e Mon Sep 17 00:00:00 2001
From: Lightczx <1686188646@qq.com>
Date: Fri, 11 Aug 2023 16:12:11 +0800
Subject: [PATCH] refactor string cultureinfo
---
src/Snap.Hutao/.editorconfig | 153 +++++++++++++++++-
.../UniversalAnalyzer.cs | 3 +
.../Snap.Hutao.Test/JsonSerializeTest.cs | 4 +-
.../Snap.Hutao/CodeMetricsConfig.txt | 1 +
.../Control/Image/CompositionImage.cs | 3 +-
.../Control/Markup/ResourceStringExtension.cs | 3 +-
.../Core/Annotation/HighQualityAttribute.cs | 2 +-
.../DatabaseCorruptedException.cs | 2 +-
.../Core/ExceptionService/ExceptionFormat.cs | 3 +-
.../UserdataCorruptedException.cs | 2 +-
.../Snap.Hutao/Core/IO/Hashing/MD5.cs | 9 +-
.../Snap.Hutao/Core/IO/Hashing/XXH64.cs | 2 +-
.../Snap.Hutao/Core/IO/Ini/IniSerializer.cs | 17 +-
.../Snap.Hutao/Core/IO/PickerExtension.cs | 2 +-
.../Snap.Hutao/Core/IO/ValueFile.cs | 1 +
.../Core/Json/Annotation/JsonEnumAttribute.cs | 2 +-
.../Json/Converter/DateTimeOffsetConverter.cs | 8 +-
.../SeparatorCommaInt32EnumerableConverter.cs | 3 +-
.../Snap.Hutao/Core/LifeCycle/Activation.cs | 14 +-
.../Snap.Hutao/Core/Setting/LocalSetting.cs | 7 +-
.../Threading/DispatcherQueueExtension.cs | 14 +-
.../Snap.Hutao/Core/TypeNameHelper.cs | 2 +-
.../Core/Windowing/ExtendedWindow.cs | 9 +-
.../Snap.Hutao/Extension/StringExtension.cs | 13 ++
.../Configuration/JsonTextValueConverter.cs | 4 +-
.../Entity/Configuration/UserConfiguration.cs | 1 +
.../Snap.Hutao/Model/Entity/GachaItem.cs | 3 +-
.../Model/Entity/SpiralAbyssEntry.cs | 2 +-
.../Model/Metadata/Avatar/FetterInfo.cs | 2 +-
.../Converter/AvatarNameCardPicConverter.cs | 2 +-
.../DescriptionsParametersDescriptor.cs | 5 +-
.../Metadata/Converter/FightPropertyFormat.cs | 2 +-
.../Model/Metadata/ParameterFormat.cs | 10 +-
.../Resource/Localization/SH.Designer.cs | 9 ++
.../Snap.Hutao/Resource/Localization/SH.resx | 9 +-
src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 2 +
.../Snap.Hutao/View/Page/SettingPage.xaml | 6 +-
.../ExperimentalFeaturesViewModel.cs | 58 -------
.../ViewModel/HutaoPassportViewModel.cs | 57 +++----
.../Snap.Hutao/ViewModel/SettingViewModel.cs | 50 ++++--
40 files changed, 328 insertions(+), 173 deletions(-)
create mode 100644 src/Snap.Hutao/Snap.Hutao/CodeMetricsConfig.txt
delete mode 100644 src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs
diff --git a/src/Snap.Hutao/.editorconfig b/src/Snap.Hutao/.editorconfig
index bea15828..fc537b99 100644
--- a/src/Snap.Hutao/.editorconfig
+++ b/src/Snap.Hutao/.editorconfig
@@ -57,6 +57,7 @@ dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_namespace_match_folder = true:suggestion
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
dotnet_style_predefined_type_for_member_access = true:silent
+dotnet_diagnostic.CA1000.severity = suggestion
[*.cs]
#### 命名样式 ####
@@ -162,7 +163,7 @@ dotnet_diagnostic.CA1309.severity = suggestion
dotnet_diagnostic.CA1805.severity = suggestion
# VSTHRD111: Use ConfigureAwait(bool)
-dotnet_diagnostic.VSTHRD111.severity = suggestion
+dotnet_diagnostic.VSTHRD111.severity = silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_prefer_readonly_struct = true:suggestion
csharp_style_prefer_utf8_string_literals = true:suggestion
@@ -172,6 +173,156 @@ dotnet_diagnostic.SA1600.severity = none
dotnet_diagnostic.SA1601.severity = silent
dotnet_diagnostic.SA1602.severity = silent
+# CA1008: 枚举应具有零值
+dotnet_diagnostic.CA1008.severity = suggestion
+
+# CA1010: 还应实现泛型接口
+dotnet_diagnostic.CA1010.severity = suggestion
+
+# CA1012: 抽象类型不应具有公共构造函数
+dotnet_diagnostic.CA1012.severity = suggestion
+
+# CA1024: 在适用处使用属性
+dotnet_diagnostic.CA1024.severity = suggestion
+
+# CA1034: 嵌套类型应不可见
+dotnet_diagnostic.CA1034.severity = suggestion
+
+# CA1036: 重写可比较类型中的方法
+dotnet_diagnostic.CA1036.severity = suggestion
+
+# CA1040: 避免使用空接口
+dotnet_diagnostic.CA1040.severity = suggestion
+
+# CA1044: 属性不应是只写的
+dotnet_diagnostic.CA1044.severity = suggestion
+
+# CA1043: 将整型或字符串参数用于索引器
+dotnet_diagnostic.CA1043.severity = suggestion
+
+# CA1046: 不要对引用类型重载相等运算符
+dotnet_diagnostic.CA1046.severity = suggestion
+
+# CA1051: 不要声明可见实例字段
+dotnet_diagnostic.CA1051.severity = suggestion
+
+# CA1052: 静态容器类型应为 Static 或 NotInheritable
+dotnet_diagnostic.CA1052.severity = suggestion
+
+# CA1058: 类型不应扩展某些基类型
+dotnet_diagnostic.CA1058.severity = suggestion
+
+# CA1063: 正确实现 IDisposable
+dotnet_diagnostic.CA1063.severity = suggestion
+
+# CA1065: 不要在意外的位置引发异常
+dotnet_diagnostic.CA1065.severity = suggestion
+
+# CA1066: 重写 Object.Equals 时实现 IEquatable
+dotnet_diagnostic.CA1066.severity = suggestion
+
+# CA1304: 指定 CultureInfo
+dotnet_diagnostic.CA1304.severity = suggestion
+
+# CA1305: 指定 IFormatProvider
+dotnet_diagnostic.CA1305.severity = suggestion
+
+# CA1307: 为了清晰起见,请指定 StringComparison
+dotnet_diagnostic.CA1307.severity = suggestion
+
+# CA1310: 为了确保正确,请指定 StringComparison
+dotnet_diagnostic.CA1310.severity = suggestion
+
+# CA1308: 将字符串规范化为大写
+dotnet_diagnostic.CA1308.severity = suggestion
+
+# CA1501: 避免过度继承
+dotnet_diagnostic.CA1501.severity = suggestion
+
+# CA1502: 避免过度复杂性
+dotnet_diagnostic.CA1502.severity = suggestion
+
+# CA1505: 避免使用无法维护的代码
+dotnet_diagnostic.CA1505.severity = suggestion
+
+# CA1506: 避免过度的类耦合
+dotnet_diagnostic.CA1506.severity = suggestion
+
+# CA1508: 避免死条件代码
+dotnet_diagnostic.CA1508.severity = suggestion
+
+# CA1810: 以内联方式初始化引用类型的静态字段
+dotnet_diagnostic.CA1810.severity = suggestion
+
+# CA1813: 避免使用非密封特性
+dotnet_diagnostic.CA1813.severity = suggestion
+
+# CA1814: 与多维数组相比,首选使用交错数组
+dotnet_diagnostic.CA1814.severity = suggestion
+
+# CA1819: 属性不应返回数组
+dotnet_diagnostic.CA1819.severity = suggestion
+
+# CA1820: 使用字符串长度测试是否有空字符串
+dotnet_diagnostic.CA1820.severity = suggestion
+
+# CA1823: 避免未使用的私有字段
+dotnet_diagnostic.CA1823.severity = suggestion
+
+# CA1849: 当在异步方法中时,调用异步方法
+dotnet_diagnostic.CA1849.severity = suggestion
+
+# CA1852: 密封内部类型
+dotnet_diagnostic.CA1852.severity = suggestion
+
+# CA2000: 丢失范围之前释放对象
+dotnet_diagnostic.CA2000.severity = suggestion
+
+# CA2002: 不要锁定具有弱标识的对象
+dotnet_diagnostic.CA2002.severity = suggestion
+
+# CA2007: 考虑对等待的任务调用 ConfigureAwait
+dotnet_diagnostic.CA2007.severity = suggestion
+
+# CA2008: 不要在未传递 TaskScheduler 的情况下创建任务
+dotnet_diagnostic.CA2008.severity = suggestion
+
+# CA2100: 检查 SQL 查询是否存在安全漏洞
+dotnet_diagnostic.CA2100.severity = suggestion
+
+# CA2109: 检查可见的事件处理程序
+dotnet_diagnostic.CA2109.severity = suggestion
+
+# CA2119: 密封满足私有接口的方法
+dotnet_diagnostic.CA2119.severity = suggestion
+
+# CA2153: 不要捕获损坏状态异常
+dotnet_diagnostic.CA2153.severity = suggestion
+
+# CA2201: 不要引发保留的异常类型
+dotnet_diagnostic.CA2201.severity = suggestion
+
+# CA2207: 以内联方式初始化值类型的静态字段
+dotnet_diagnostic.CA2207.severity = suggestion
+
+# CA2213: 应释放可释放的字段
+dotnet_diagnostic.CA2213.severity = suggestion
+
+# CA2214: 不要在构造函数中调用可重写的方法
+dotnet_diagnostic.CA2214.severity = suggestion
+
+# CA2215: Dispose 方法应调用基类释放
+dotnet_diagnostic.CA2215.severity = suggestion
+
+# CA2216: 可释放类型应声明终结器
+dotnet_diagnostic.CA2216.severity = suggestion
+
+# CA2227: 集合属性应为只读
+dotnet_diagnostic.CA2227.severity = suggestion
+
+# CA2251: 使用 “string.Equals”
+dotnet_diagnostic.CA2251.severity = suggestion
+
[*.vb]
#### 命名样式 ####
diff --git a/src/Snap.Hutao/Snap.Hutao.SourceGeneration/UniversalAnalyzer.cs b/src/Snap.Hutao/Snap.Hutao.SourceGeneration/UniversalAnalyzer.cs
index 31b679d4..cbffff49 100644
--- a/src/Snap.Hutao/Snap.Hutao.SourceGeneration/UniversalAnalyzer.cs
+++ b/src/Snap.Hutao/Snap.Hutao.SourceGeneration/UniversalAnalyzer.cs
@@ -78,6 +78,9 @@ internal sealed class UniversalAnalyzer : DiagnosticAnalyzer
context.RegisterSyntaxNodeAction(HandleEqualsAndNotEqualsExpressionShouldUsePatternMatching, expressions);
context.RegisterSyntaxNodeAction(HandleIsPatternShouldUseRecursivePattern, SyntaxKind.IsPatternExpression);
context.RegisterSyntaxNodeAction(HandleArgumentNullExceptionThrowIfNull, SyntaxKind.SuppressNullableWarningExpression);
+
+ // TODO add analyzer for unnecessary IServiceProvider registration
+ // TODO add analyzer for Singlton service use Scoped or Transient services
}
private static void HandleTypeShouldBeInternal(SyntaxNodeAnalysisContext context)
diff --git a/src/Snap.Hutao/Snap.Hutao.Test/JsonSerializeTest.cs b/src/Snap.Hutao/Snap.Hutao.Test/JsonSerializeTest.cs
index bfc05c2c..eb6473bb 100644
--- a/src/Snap.Hutao/Snap.Hutao.Test/JsonSerializeTest.cs
+++ b/src/Snap.Hutao/Snap.Hutao.Test/JsonSerializeTest.cs
@@ -53,13 +53,13 @@ public class JsonSerializeTest
Assert.AreEqual(sample[111], "12");
}
- private class Sample
+ private sealed class Sample
{
public int A { get => B; set => B = value; }
public int B { get; set; }
}
- private class StringNumberSample
+ private sealed class StringNumberSample
{
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
public int A { get; set; }
diff --git a/src/Snap.Hutao/Snap.Hutao/CodeMetricsConfig.txt b/src/Snap.Hutao/Snap.Hutao/CodeMetricsConfig.txt
new file mode 100644
index 00000000..7e7498af
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/CodeMetricsConfig.txt
@@ -0,0 +1 @@
+CA1501: 6
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs b/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs
index dfe468a0..7ffe983a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Control/Image/CompositionImage.cs
@@ -10,6 +10,7 @@ using Snap.Hutao.Control.Animation;
using Snap.Hutao.Control.Extension;
using Snap.Hutao.Core.Caching;
using Snap.Hutao.Service.Notification;
+using System.Globalization;
using System.IO;
using System.Net.Http;
using System.Runtime.InteropServices;
@@ -110,7 +111,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
if (exception is HttpRequestException httpRequestException)
{
- infoBarService.Error(httpRequestException, string.Format(SH.ControlImageCompositionImageHttpRequest, uri));
+ infoBarService.Error(httpRequestException, SH.ControlImageCompositionImageHttpRequest.Format(uri));
}
else
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Markup/ResourceStringExtension.cs b/src/Snap.Hutao/Snap.Hutao/Control/Markup/ResourceStringExtension.cs
index 2e71149d..92de4ac5 100644
--- a/src/Snap.Hutao/Snap.Hutao/Control/Markup/ResourceStringExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Control/Markup/ResourceStringExtension.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Markup;
+using System.Globalization;
namespace Snap.Hutao.Control.Markup;
@@ -20,6 +21,6 @@ internal sealed class ResourceStringExtension : MarkupExtension
///
protected override object ProvideValue()
{
- return SH.ResourceManager.GetString(Name ?? string.Empty) ?? Name ?? string.Empty;
+ return SH.ResourceManager.GetString(Name ?? string.Empty, CultureInfo.CurrentCulture) ?? Name ?? string.Empty;
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Annotation/HighQualityAttribute.cs b/src/Snap.Hutao/Snap.Hutao/Core/Annotation/HighQualityAttribute.cs
index b98f4f2b..0757aaf0 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Annotation/HighQualityAttribute.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Annotation/HighQualityAttribute.cs
@@ -7,6 +7,6 @@ namespace Snap.Hutao.Core.Annotation;
/// 高质量代码
///
[AttributeUsage(AttributeTargets.All, Inherited = false)]
-internal class HighQualityAttribute : Attribute
+internal sealed class HighQualityAttribute : Attribute
{
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/DatabaseCorruptedException.cs b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/DatabaseCorruptedException.cs
index bfc11386..1c31ff82 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/DatabaseCorruptedException.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/DatabaseCorruptedException.cs
@@ -15,7 +15,7 @@ internal sealed class DatabaseCorruptedException : Exception
/// 消息
/// 内部错误
public DatabaseCorruptedException(string message, Exception? innerException)
- : base(string.Format(SH.CoreExceptionServiceDatabaseCorruptedMessage, $"{message}\n{innerException?.Message}"), innerException)
+ : base(SH.CoreExceptionServiceDatabaseCorruptedMessage.Format($"{message}\n{innerException?.Message}"), innerException)
{
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionFormat.cs b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionFormat.cs
index de50e2e8..489bef51 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionFormat.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionFormat.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using System.Collections;
+using System.Globalization;
using System.Text;
namespace Snap.Hutao.Core.ExceptionService;
@@ -25,7 +26,7 @@ internal sealed class ExceptionFormat
foreach (DictionaryEntry entry in exception.Data)
{
- builder.AppendLine($"{entry.Key}:[{TypeNameHelper.GetTypeDisplayName(entry.Value)}]:entry.Value");
+ builder.AppendLine(CultureInfo.CurrentCulture, $"[{TypeNameHelper.GetTypeDisplayName(entry.Value)}]:{entry.Key}:{entry.Value}");
}
builder.AppendLine(SectionSeparator);
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/UserdataCorruptedException.cs b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/UserdataCorruptedException.cs
index dae43281..ee6880d8 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/UserdataCorruptedException.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/UserdataCorruptedException.cs
@@ -15,7 +15,7 @@ internal sealed class UserdataCorruptedException : Exception
/// 消息
/// 内部错误
public UserdataCorruptedException(string message, Exception? innerException)
- : base(string.Format(SH.CoreExceptionServiceUserdataCorruptedMessage, $"{message}\n{innerException?.Message}"), innerException)
+ : base(SH.CoreExceptionServiceUserdataCorruptedMessage.Format($"{message}\n{innerException?.Message}"), innerException)
{
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/MD5.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/MD5.cs
index 52c50631..47f4e25a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/MD5.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/MD5.cs
@@ -19,7 +19,7 @@ internal static class MD5
/// 文件 Md5 摘要
public static async ValueTask HashFileAsync(string filePath, CancellationToken token = default)
{
- await using (FileStream stream = File.OpenRead(filePath))
+ using (FileStream stream = File.OpenRead(filePath))
{
return await HashAsync(stream, token).ConfigureAwait(false);
}
@@ -33,10 +33,7 @@ internal static class MD5
/// 流 Md5 摘要
public static async ValueTask HashAsync(Stream stream, CancellationToken token = default)
{
- using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
- {
- byte[] bytes = await md5.ComputeHashAsync(stream, token).ConfigureAwait(false);
- return System.Convert.ToHexString(bytes);
- }
+ byte[] bytes = await System.Security.Cryptography.MD5.HashDataAsync(stream, token).ConfigureAwait(false);
+ return System.Convert.ToHexString(bytes);
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/XXH64.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/XXH64.cs
index e68d285a..6999bb5e 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/XXH64.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/XXH64.cs
@@ -33,7 +33,7 @@ internal static class XXH64
/// 摘要
public static async ValueTask HashFileAsync(string path, CancellationToken token = default)
{
- await using (FileStream stream = File.OpenRead(path))
+ using (FileStream stream = File.OpenRead(path))
{
return await HashAsync(stream, token).ConfigureAwait(false);
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/Ini/IniSerializer.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/Ini/IniSerializer.cs
index 9a9b659c..15293298 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/IO/Ini/IniSerializer.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/Ini/IniSerializer.cs
@@ -22,25 +22,26 @@ internal static class IniSerializer
{
while (reader.ReadLine() is { } line)
{
- if (line.Length <= 0)
+ if (string.IsNullOrEmpty(line))
{
continue;
}
- if (line[0] == '[')
+ ReadOnlySpan lineSpan = line;
+
+ if (lineSpan[0] is '[')
{
- yield return new IniSection(line[1..^1]);
+ yield return new IniSection(lineSpan[1..^1].ToString());
}
- if (line[0] == ';')
+ if (lineSpan[0] is ';')
{
- yield return new IniComment(line[1..]);
+ yield return new IniComment(lineSpan[1..].ToString());
}
- if (line.IndexOf('=') > 0)
+ if (lineSpan.TrySplitIntoTwo('=', out ReadOnlySpan left, out ReadOnlySpan right))
{
- string[] parameters = line.Split('=', 2, StringSplitOptions.TrimEntries);
- yield return new IniParameter(parameters[0], parameters[1]);
+ yield return new IniParameter(left.Trim().ToString(), right.Trim().ToString());
}
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs
index 11169cb9..76cf669e 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs
@@ -98,7 +98,7 @@ internal static class PickerExtension
.GetRequiredService()
.Warning(
SH.CoreIOPickerExtensionPickerExceptionInfoBarTitle,
- string.Format(SH.CoreIOPickerExtensionPickerExceptionInfoBarMessage, exception.Message));
+ SH.CoreIOPickerExtensionPickerExceptionInfoBarMessage.Format(exception.Message));
}
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/ValueFile.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/ValueFile.cs
index 8e48cc36..cdd0b610 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/IO/ValueFile.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/ValueFile.cs
@@ -80,6 +80,7 @@ internal readonly struct ValueFile
}
///
+ [SuppressMessage("", "CA1307")]
public override int GetHashCode()
{
return value.GetHashCode();
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Json/Annotation/JsonEnumAttribute.cs b/src/Snap.Hutao/Snap.Hutao/Core/Json/Annotation/JsonEnumAttribute.cs
index 5b5d71c8..5c0515a1 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Json/Annotation/JsonEnumAttribute.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Json/Annotation/JsonEnumAttribute.cs
@@ -10,7 +10,7 @@ namespace Snap.Hutao.Core.Json.Annotation;
/// Json 枚举类型
///
[AttributeUsage(AttributeTargets.Property)]
-internal class JsonEnumAttribute : Attribute
+internal sealed class JsonEnumAttribute : Attribute
{
private static readonly Type UnsafeEnumConverterType = typeof(UnsafeEnumConverter<>);
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Json/Converter/DateTimeOffsetConverter.cs b/src/Snap.Hutao/Snap.Hutao/Core/Json/Converter/DateTimeOffsetConverter.cs
index 9f118f89..be8eaef3 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Json/Converter/DateTimeOffsetConverter.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Json/Converter/DateTimeOffsetConverter.cs
@@ -1,6 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using System.Globalization;
+
namespace Snap.Hutao.Core.Json.Converter;
///
@@ -9,12 +11,14 @@ namespace Snap.Hutao.Core.Json.Converter;
[HighQuality]
internal class DateTimeOffsetConverter : JsonConverter
{
+ private const string Format = "yyyy-MM-dd HH:mm:ss";
+
///
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.GetString() is { } dataTimeString)
{
- return DateTimeOffset.Parse(dataTimeString);
+ return DateTimeOffset.ParseExact(dataTimeString, Format, CultureInfo.CurrentCulture);
}
return default;
@@ -23,6 +27,6 @@ internal class DateTimeOffsetConverter : JsonConverter
///
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
- writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
+ writer.WriteStringValue(value.ToString(Format, CultureInfo.CurrentCulture));
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Json/Converter/SeparatorCommaInt32EnumerableConverter.cs b/src/Snap.Hutao/Snap.Hutao/Core/Json/Converter/SeparatorCommaInt32EnumerableConverter.cs
index 183e37c3..bffefbb1 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Json/Converter/SeparatorCommaInt32EnumerableConverter.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Json/Converter/SeparatorCommaInt32EnumerableConverter.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Microsoft.Extensions.Primitives;
+using System.Globalization;
namespace Snap.Hutao.Core.Json.Converter;
@@ -35,7 +36,7 @@ internal sealed class SeparatorCommaInt32EnumerableConverter : JsonConverter
public const string ImportUIAFFromClipboard = nameof(ImportUIAFFromClipboard);
- private const string CategoryAchievement = "achievement";
- private const string CategoryDailyNote = "dailynote";
- private const string UrlActionImport = "/import";
- private const string UrlActionRefresh = "/refresh";
+ private const string CategoryAchievement = "ACHIEVEMENT";
+ private const string CategoryDailyNote = "DAILYNOTE";
+ private const string UrlActionImport = "/IMPORT";
+ private const string UrlActionRefresh = "/REFRESH";
private readonly IServiceProvider serviceProvider;
private readonly ITaskContext taskContext;
@@ -187,9 +187,9 @@ internal sealed class Activation : IActivation
{
UriBuilder builder = new(uri);
- string category = builder.Host.ToLowerInvariant();
- string action = builder.Path.ToLowerInvariant();
- string parameter = builder.Query.ToLowerInvariant();
+ string category = builder.Host.ToUpperInvariant();
+ string action = builder.Path.ToUpperInvariant();
+ string parameter = builder.Query.ToUpperInvariant();
switch (category)
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Setting/LocalSetting.cs b/src/Snap.Hutao/Snap.Hutao/Core/Setting/LocalSetting.cs
index 0892aa5c..23a50292 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Setting/LocalSetting.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Setting/LocalSetting.cs
@@ -11,12 +11,7 @@ namespace Snap.Hutao.Core.Setting;
[HighQuality]
internal static class LocalSetting
{
- private static readonly ApplicationDataContainer Container;
-
- static LocalSetting()
- {
- Container = ApplicationData.Current.LocalSettings;
- }
+ private static readonly ApplicationDataContainer Container = ApplicationData.Current.LocalSettings;
///
public static byte Get(string key, byte defaultValue)
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatcherQueueExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatcherQueueExtension.cs
index 9bfa00f4..a353ad31 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatcherQueueExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatcherQueueExtension.cs
@@ -18,13 +18,15 @@ internal static class DispatcherQueueExtension
/// 执行的回调
public static void Invoke(this DispatcherQueue dispatcherQueue, Action action)
{
- ManualResetEventSlim blockEvent = new();
- dispatcherQueue.TryEnqueue(() =>
+ using (ManualResetEventSlim blockEvent = new())
{
- action();
- blockEvent.Set();
- });
+ dispatcherQueue.TryEnqueue(() =>
+ {
+ action();
+ blockEvent.Set();
+ });
- blockEvent.Wait();
+ blockEvent.Wait();
+ }
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/TypeNameHelper.cs b/src/Snap.Hutao/Snap.Hutao/Core/TypeNameHelper.cs
index 50813f17..66b635b9 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/TypeNameHelper.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/TypeNameHelper.cs
@@ -161,7 +161,7 @@ internal static class TypeNameHelper
}
}
- int genericPartIndex = type.Name.IndexOf('`');
+ int genericPartIndex = type.Name.AsSpan().IndexOf('`');
if (genericPartIndex <= 0)
{
builder.Append(type.Name);
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs
index 0ec57711..8647fee6 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs
@@ -29,7 +29,7 @@ internal sealed class ExtendedWindow : IRecipient? subclass;
+ private readonly WindowSubclass subclass;
private ExtendedWindow(TWindow window, IServiceProvider serviceProvider)
{
@@ -63,7 +63,7 @@ internal sealed class ExtendedWindow : IRecipient();
WindowOptions options = window.WindowOptions;
- window.AppWindow.Title = string.Format(SH.AppNameAndVersion, hutaoOptions.Version);
+ window.AppWindow.Title = SH.AppNameAndVersion.Format(hutaoOptions.Version);
window.AppWindow.SetIcon(Path.Combine(hutaoOptions.InstalledLocation, "Assets/Logo.ico"));
ExtendsContentIntoTitleBar();
@@ -79,7 +79,7 @@ internal sealed class ExtendedWindow : IRecipient().Register(this);
@@ -91,7 +91,8 @@ internal sealed class ExtendedWindow : IRecipient : ValueConverter
{
- ///
- /// Initializes a new instance of the class.
- ///
+ [SuppressMessage("", "SH007")]
public JsonTextValueConverter()
: base(
obj => JsonSerializer.Serialize(obj, JsonOptions.Default),
diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/UserConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/UserConfiguration.cs
index e62357c9..d25053da 100644
--- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/UserConfiguration.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/Configuration/UserConfiguration.cs
@@ -14,6 +14,7 @@ namespace Snap.Hutao.Model.Entity.Configuration;
internal sealed class UserConfiguration : IEntityTypeConfiguration
{
///
+ [SuppressMessage("", "SH007")]
public void Configure(EntityTypeBuilder builder)
{
builder.Property(e => e.CookieToken)
diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/GachaItem.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/GachaItem.cs
index 18cca2f4..0da36891 100644
--- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/GachaItem.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/GachaItem.cs
@@ -7,6 +7,7 @@ using Snap.Hutao.Model.Metadata.Abstraction;
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
+using System.Globalization;
namespace Snap.Hutao.Model.Entity;
@@ -119,7 +120,7 @@ internal sealed partial class GachaItem
ArchiveId = archiveId,
GachaType = item.GachaType,
QueryType = item.UIGFGachaType,
- ItemId = uint.Parse(item.ItemId),
+ ItemId = uint.Parse(item.ItemId, CultureInfo.CurrentCulture),
Time = item.Time,
Id = item.Id,
};
diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs
index 598123b1..ad52f3b8 100644
--- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SpiralAbyssEntry.cs
@@ -32,7 +32,7 @@ internal sealed class SpiralAbyssEntry : ObservableObject,
/// 视图 中使用的计划 Id 字符串
///
[NotMapped]
- public string Schedule { get => string.Format(SH.ModelEntitySpiralAbyssScheduleFormat, ScheduleId); }
+ public string Schedule { get => SH.ModelEntitySpiralAbyssScheduleFormat.Format(ScheduleId); }
///
/// Uid
diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/FetterInfo.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/FetterInfo.cs
index 6464e494..bea90e4d 100644
--- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/FetterInfo.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/FetterInfo.cs
@@ -47,7 +47,7 @@ internal sealed class FetterInfo
///
public string BirthFormatted
{
- get => string.Format(SH.ModelMetadataFetterInfoBirthdayFormat, BirthMonth, BirthDay);
+ get => SH.ModelMetadataFetterInfoBirthdayFormat.Format(BirthMonth, BirthDay);
}
///
diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AvatarNameCardPicConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AvatarNameCardPicConverter.cs
index d81abc38..537ab313 100644
--- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AvatarNameCardPicConverter.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AvatarNameCardPicConverter.cs
@@ -20,7 +20,7 @@ internal sealed class AvatarNameCardPicConverter : ValueConverter $"{MathF.Round(value, MidpointRounding.AwayFromZero)}",
FormatMethod.Percent => $"{value:P1}",
- _ => value.ToString(),
+ _ => $"{value}",
};
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/ParameterFormat.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/ParameterFormat.cs
index d80eea9a..ee136936 100644
--- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/ParameterFormat.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/ParameterFormat.cs
@@ -17,7 +17,7 @@ internal sealed class ParameterFormat : IFormatProvider, ICustomFormatter
/// 字符串
/// 参数
/// 格式化的字符串
- public static string Format(string str, object param)
+ public static string Format(string str, object param, IFormatProvider? formatProvider = default)
{
return string.Format(LazyFormat.Value, str, param);
}
@@ -29,16 +29,16 @@ internal sealed class ParameterFormat : IFormatProvider, ICustomFormatter
switch (fmtSpan.Length)
{
case 3: // FnP
- return string.Format($"{{0:P{fmtSpan[1]}}}", arg);
+ return string.Format(formatProvider, $"{{0:P{fmtSpan[1]}}}", arg);
case 2: // Fn
- return string.Format($"{{0:{fmtSpan}}}", arg);
+ return string.Format(formatProvider, $"{{0:{fmtSpan}}}", arg);
case 1: // P I
switch (fmtSpan[0])
{
case 'P':
- return string.Format($"{{0:P0}}", arg);
+ return string.Format(formatProvider, $"{{0:P0}}", arg);
case 'I':
- return arg is null ? "0" : ((IConvertible)arg).ToInt32(default).ToString();
+ return arg is null ? "0" : ((IConvertible)arg).ToInt32(default).ToString(formatProvider);
}
break;
diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs
index 68d37009..42b8fb9c 100644
--- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs
@@ -2733,6 +2733,15 @@ namespace Snap.Hutao.Resource.Localization {
}
}
+ ///
+ /// 查找类似 请输入正确的邮箱 的本地化字符串。
+ ///
+ internal static string ViewModelHutaoPassportEmailNotValidHint {
+ get {
+ return ResourceManager.GetString("ViewModelHutaoPassportEmailNotValidHint", resourceCulture);
+ }
+ }
+
///
/// 查找类似 剪贴板中的文本格式不正确 的本地化字符串。
///
diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
index 9461be20..aba5c5d6 100644
--- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
+++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
@@ -824,12 +824,12 @@
探索派遣完成提醒
-
- 原粹树脂提醒阈值
-
洞天宝钱提醒阈值
+
+ 原粹树脂提醒阈值
+
在主页显示卡片
@@ -1064,6 +1064,9 @@
正在上传到胡桃云服务
+
+ 请输入正确的邮箱
+
剪贴板中的文本格式不正确
diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
index 2543fed3..4f6ee785 100644
--- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
+++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
@@ -71,6 +71,7 @@
+
@@ -161,6 +162,7 @@
+
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml
index 79d01458..a7b9acd4 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml
@@ -150,7 +150,7 @@
-/// 实验性功能视图模型
-///
-[HighQuality]
-[ConstructorGenerated]
-[Injection(InjectAs.Scoped)]
-internal sealed partial class ExperimentalFeaturesViewModel : ObservableObject
-{
- private readonly IServiceProvider serviceProvider;
-
- [Command("OpenCacheFolderCommand")]
- private Task OpenCacheFolderAsync()
- {
- RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService();
- return Launcher.LaunchFolderPathAsync(hutaoOptions.LocalCache).AsTask();
- }
-
- [Command("OpenDataFolderCommand")]
- private Task OpenDataFolderAsync()
- {
- RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService();
- return Launcher.LaunchFolderPathAsync(hutaoOptions.DataFolder).AsTask();
- }
-
- [Command("DeleteUsersCommand")]
- private async Task DangerousDeleteUsersAsync()
- {
- using (IServiceScope scope = serviceProvider.CreateScope())
- {
- ContentDialogResult result = await scope.ServiceProvider
- .GetRequiredService()
- .CreateForConfirmCancelAsync(SH.ViewDialogSettingDeleteUserDataTitle, SH.ViewDialogSettingDeleteUserDataContent)
- .ConfigureAwait(false);
-
- if (result == ContentDialogResult.Primary)
- {
- AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
- await appDbContext.Users.ExecuteDeleteAsync().ConfigureAwait(false);
-
- AppInstance.Restart(string.Empty);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoPassportViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoPassportViewModel.cs
index d44e0a61..3833ad71 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoPassportViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoPassportViewModel.cs
@@ -1,12 +1,14 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using CommunityToolkit.Common;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Service.Hutao;
using Snap.Hutao.Service.Navigation;
using Snap.Hutao.Service.Notification;
using Snap.Hutao.Web.Hutao;
using Snap.Hutao.Web.Response;
+using System.Text.RegularExpressions;
namespace Snap.Hutao.ViewModel;
@@ -17,9 +19,12 @@ namespace Snap.Hutao.ViewModel;
[Injection(InjectAs.Scoped)]
internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel
{
- private readonly IServiceProvider serviceProvider;
- private readonly ITaskContext taskContext;
private readonly HomaPassportClient homaPassportClient;
+ private readonly INavigationService navigationService;
+ private readonly HutaoUserOptions hutaoUserOptions;
+ private readonly IServiceProvider serviceProvider;
+ private readonly IInfoBarService infoBarService;
+ private readonly ITaskContext taskContext;
private string? userName;
private string? password;
@@ -40,22 +45,16 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel
///
public string? VerifyCode { get => verifyCode; set => SetProperty(ref verifyCode, value); }
- ///
- protected override Task OpenUIAsync()
- {
- return Task.CompletedTask;
- }
-
[Command("RegisterVerifyCommand")]
private Task RegisterVerifyAsync()
{
- return VerifyAsync(false);
+ return VerifyAsync(false).AsTask();
}
[Command("RegisterCommand")]
private async Task RegisterAsync()
{
- if (UserName == null || Password == null || VerifyCode == null)
+ if (UserName is null || Password is null || VerifyCode is null)
{
return;
}
@@ -65,13 +64,12 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel
if (response.IsOk())
{
SaveUserNameAndPassword();
- serviceProvider.GetRequiredService().Information(response.Message);
+ infoBarService.Information(response.Message);
await taskContext.SwitchToMainThreadAsync();
- serviceProvider.GetRequiredService().LoginSucceed(UserName, response.Data);
+ hutaoUserOptions.LoginSucceed(UserName, response.Data);
- await serviceProvider
- .GetRequiredService()
+ await navigationService
.NavigateAsync(INavigationAwaiter.Default, true)
.ConfigureAwait(false);
}
@@ -80,13 +78,13 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel
[Command("ResetPasswordVerifyCommand")]
private Task ResetPasswordVerifyAsync()
{
- return VerifyAsync(true);
+ return VerifyAsync(true).AsTask();
}
[Command("ResetPasswordCommand")]
private async Task ResetPasswordAsync()
{
- if (UserName == null || Password == null || VerifyCode == null)
+ if (UserName is null || Password is null || VerifyCode is null)
{
return;
}
@@ -96,13 +94,12 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel
if (response.IsOk())
{
SaveUserNameAndPassword();
- serviceProvider.GetRequiredService().Information(response.Message);
+ infoBarService.Information(response.Message);
await taskContext.SwitchToMainThreadAsync();
- serviceProvider.GetRequiredService().LoginSucceed(UserName, response.Data);
+ hutaoUserOptions.LoginSucceed(UserName, response.Data);
- await serviceProvider
- .GetRequiredService()
+ await navigationService
.NavigateAsync(INavigationAwaiter.Default, true)
.ConfigureAwait(false);
}
@@ -111,7 +108,7 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel
[Command("LoginCommand")]
private async Task LoginAsync()
{
- if (UserName == null || Password == null)
+ if (UserName is null || Password is null)
{
return;
}
@@ -121,32 +118,36 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel
if (response.IsOk())
{
SaveUserNameAndPassword();
- serviceProvider.GetRequiredService().Information(response.Message);
+ infoBarService.Information(response.Message);
await taskContext.SwitchToMainThreadAsync();
- serviceProvider.GetRequiredService().LoginSucceed(UserName, response.Data);
+ hutaoUserOptions.LoginSucceed(UserName, response.Data);
- await serviceProvider
- .GetRequiredService()
+ await navigationService
.NavigateAsync(INavigationAwaiter.Default, true)
.ConfigureAwait(false);
}
}
- private async Task VerifyAsync(bool isResetPassword)
+ private async ValueTask VerifyAsync(bool isResetPassword)
{
- if (UserName == null)
+ if (string.IsNullOrEmpty(UserName))
{
return;
}
+ if (!UserName.IsEmail())
+ {
+ infoBarService.Warning(SH.ViewModelHutaoPassportEmailNotValidHint);
+ }
+
Response response = await homaPassportClient.VerifyAsync(UserName, isResetPassword).ConfigureAwait(false);
serviceProvider.GetRequiredService().Information(response.Message);
}
private void SaveUserNameAndPassword()
{
- if (UserName != null && Password != null)
+ if (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password))
{
LocalSetting.Set(SettingKeys.PassportUserName, UserName);
LocalSetting.Set(SettingKeys.PassportPassword, Password);
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs
index 3fc8d36a..1fc4e9b5 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs
@@ -1,11 +1,12 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using Microsoft.EntityFrameworkCore;
+using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.AppLifecycle;
using Snap.Hutao.Core;
using Snap.Hutao.Core.IO;
using Snap.Hutao.Core.IO.DataTransfer;
-using Snap.Hutao.Core.LifeCycle;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Core.Windowing;
using Snap.Hutao.Factory.Abstraction;
@@ -13,7 +14,6 @@ using Snap.Hutao.Model;
using Snap.Hutao.Model.Entity.Database;
using Snap.Hutao.Service;
using Snap.Hutao.Service.GachaLog.QueryProvider;
-using Snap.Hutao.Service.Game;
using Snap.Hutao.Service.Game.Locator;
using Snap.Hutao.Service.Hutao;
using Snap.Hutao.Service.Navigation;
@@ -22,6 +22,7 @@ using Snap.Hutao.View.Dialog;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
+using Windows.System;
namespace Snap.Hutao.ViewModel;
@@ -35,13 +36,9 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
{
private readonly IServiceProvider serviceProvider;
private readonly ITaskContext taskContext;
- private readonly AppDbContext appDbContext;
- private readonly IGameService gameService;
- private readonly ILogger logger;
private readonly AppOptions options;
- private readonly RuntimeOptions hutaoOptions;
+ private readonly RuntimeOptions runtimeOptions;
private readonly HutaoUserOptions hutaoUserOptions;
- private readonly ExperimentalFeaturesViewModel experimental;
private NameValue? selectedBackdropType;
private NameValue? selectedCulture;
@@ -54,7 +51,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
///
/// 胡桃选项
///
- public RuntimeOptions HutaoOptions { get => hutaoOptions; }
+ public RuntimeOptions HutaoOptions { get => runtimeOptions; }
///
/// 胡桃用户选项
@@ -95,11 +92,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
}
}
- ///
- /// 实验性功能
- ///
- public ExperimentalFeaturesViewModel Experimental { get => experimental; }
-
///
protected override Task OpenUIAsync()
{
@@ -216,4 +208,36 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
{
serviceProvider.GetRequiredService().Navigate(INavigationAwaiter.Default);
}
+
+ [Command("OpenCacheFolderCommand")]
+ private Task OpenCacheFolderAsync()
+ {
+ return Launcher.LaunchFolderPathAsync(runtimeOptions.LocalCache).AsTask();
+ }
+
+ [Command("OpenDataFolderCommand")]
+ private Task OpenDataFolderAsync()
+ {
+ return Launcher.LaunchFolderPathAsync(runtimeOptions.DataFolder).AsTask();
+ }
+
+ [Command("DeleteUsersCommand")]
+ private async Task DangerousDeleteUsersAsync()
+ {
+ using (IServiceScope scope = serviceProvider.CreateScope())
+ {
+ ContentDialogResult result = await scope.ServiceProvider
+ .GetRequiredService()
+ .CreateForConfirmCancelAsync(SH.ViewDialogSettingDeleteUserDataTitle, SH.ViewDialogSettingDeleteUserDataContent)
+ .ConfigureAwait(false);
+
+ if (result == ContentDialogResult.Primary)
+ {
+ AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService();
+ await appDbContext.Users.ExecuteDeleteAsync().ConfigureAwait(false);
+
+ AppInstance.Restart(string.Empty);
+ }
+ }
+ }
}
\ No newline at end of file