mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
refactor string cultureinfo
This commit is contained in:
@@ -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]
|
||||
#### 命名样式 ####
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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; }
|
||||
|
||||
1
src/Snap.Hutao/Snap.Hutao/CodeMetricsConfig.txt
Normal file
1
src/Snap.Hutao/Snap.Hutao/CodeMetricsConfig.txt
Normal file
@@ -0,0 +1 @@
|
||||
CA1501: 6
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
/// <inheritdoc/>
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,6 @@ namespace Snap.Hutao.Core.Annotation;
|
||||
/// 高质量代码
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false)]
|
||||
internal class HighQualityAttribute : Attribute
|
||||
internal sealed class HighQualityAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -15,7 +15,7 @@ internal sealed class DatabaseCorruptedException : Exception
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="innerException">内部错误</param>
|
||||
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)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -15,7 +15,7 @@ internal sealed class UserdataCorruptedException : Exception
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="innerException">内部错误</param>
|
||||
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)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ internal static class MD5
|
||||
/// <returns>文件 Md5 摘要</returns>
|
||||
public static async ValueTask<string> 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
|
||||
/// <returns>流 Md5 摘要</returns>
|
||||
public static async ValueTask<string> 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);
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ internal static class XXH64
|
||||
/// <returns>摘要</returns>
|
||||
public static async ValueTask<string> 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);
|
||||
}
|
||||
|
||||
@@ -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<char> 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<char> left, out ReadOnlySpan<char> 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ internal static class PickerExtension
|
||||
.GetRequiredService<IInfoBarService>()
|
||||
.Warning(
|
||||
SH.CoreIOPickerExtensionPickerExceptionInfoBarTitle,
|
||||
string.Format(SH.CoreIOPickerExtensionPickerExceptionInfoBarMessage, exception.Message));
|
||||
SH.CoreIOPickerExtensionPickerExceptionInfoBarMessage.Format(exception.Message));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,7 @@ internal readonly struct ValueFile
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
[SuppressMessage("", "CA1307")]
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value.GetHashCode();
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Snap.Hutao.Core.Json.Annotation;
|
||||
/// Json 枚举类型
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
internal class JsonEnumAttribute : Attribute
|
||||
internal sealed class JsonEnumAttribute : Attribute
|
||||
{
|
||||
private static readonly Type UnsafeEnumConverterType = typeof(UnsafeEnumConverter<>);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
@@ -9,12 +11,14 @@ namespace Snap.Hutao.Core.Json.Converter;
|
||||
[HighQuality]
|
||||
internal class DateTimeOffsetConverter : JsonConverter<DateTimeOffset>
|
||||
{
|
||||
private const string Format = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
/// <inheritdoc/>
|
||||
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<DateTimeOffset>
|
||||
/// <inheritdoc/>
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -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<IEn
|
||||
// TODO: Use Collection Literals
|
||||
foreach (StringSegment id in new StringTokenizer(source, new[] { Comma }))
|
||||
{
|
||||
yield return int.Parse(id.AsSpan());
|
||||
yield return int.Parse(id.AsSpan(), CultureInfo.CurrentCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,10 +42,10 @@ internal sealed class Activation : IActivation
|
||||
/// </summary>
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static byte Get(string key, byte defaultValue)
|
||||
|
||||
@@ -18,13 +18,15 @@ internal static class DispatcherQueueExtension
|
||||
/// <param name="action">执行的回调</param>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -29,7 +29,7 @@ internal sealed class ExtendedWindow<TWindow> : IRecipient<FlyoutStateChangedMes
|
||||
{
|
||||
private readonly TWindow window;
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly WindowSubclass<TWindow>? subclass;
|
||||
private readonly WindowSubclass<TWindow> subclass;
|
||||
|
||||
private ExtendedWindow(TWindow window, IServiceProvider serviceProvider)
|
||||
{
|
||||
@@ -63,7 +63,7 @@ internal sealed class ExtendedWindow<TWindow> : IRecipient<FlyoutStateChangedMes
|
||||
RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
|
||||
|
||||
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<TWindow> : IRecipient<FlyoutStateChangedMes
|
||||
UpdateSystemBackdrop(appOptions.BackdropType);
|
||||
appOptions.PropertyChanged += OnOptionsPropertyChanged;
|
||||
|
||||
subclass!.Initialize();
|
||||
subclass.Initialize();
|
||||
|
||||
serviceProvider.GetRequiredService<IMessenger>().Register(this);
|
||||
|
||||
@@ -91,7 +91,8 @@ internal sealed class ExtendedWindow<TWindow> : IRecipient<FlyoutStateChangedMes
|
||||
{
|
||||
if (e.PropertyName == nameof(AppOptions.BackdropType))
|
||||
{
|
||||
UpdateSystemBackdrop(((AppOptions)sender!).BackdropType);
|
||||
ArgumentNullException.ThrowIfNull(sender);
|
||||
UpdateSystemBackdrop(((AppOptions)sender).BackdropType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Snap.Hutao.Extension;
|
||||
@@ -27,4 +28,16 @@ internal static class StringExtension
|
||||
{
|
||||
return source.AsSpan().TrimEnd(value).ToString();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string Format(this string value, object? arg)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, value, arg);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string Format(this string value, object? arg0, object? arg1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, value, arg0, arg1);
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,7 @@ namespace Snap.Hutao.Model.Entity.Configuration;
|
||||
[HighQuality]
|
||||
internal sealed class JsonTextValueConverter<TProperty> : ValueConverter<TProperty, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonTextValueConverter{TProperty}"/> class.
|
||||
/// </summary>
|
||||
[SuppressMessage("", "SH007")]
|
||||
public JsonTextValueConverter()
|
||||
: base(
|
||||
obj => JsonSerializer.Serialize(obj, JsonOptions.Default),
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Snap.Hutao.Model.Entity.Configuration;
|
||||
internal sealed class UserConfiguration : IEntityTypeConfiguration<User>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[SuppressMessage("", "SH007")]
|
||||
public void Configure(EntityTypeBuilder<User> builder)
|
||||
{
|
||||
builder.Property(e => e.CookieToken)
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ internal sealed class SpiralAbyssEntry : ObservableObject,
|
||||
/// 视图 中使用的计划 Id 字符串
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string Schedule { get => string.Format(SH.ModelEntitySpiralAbyssScheduleFormat, ScheduleId); }
|
||||
public string Schedule { get => SH.ModelEntitySpiralAbyssScheduleFormat.Format(ScheduleId); }
|
||||
|
||||
/// <summary>
|
||||
/// Uid
|
||||
|
||||
@@ -47,7 +47,7 @@ internal sealed class FetterInfo
|
||||
/// </summary>
|
||||
public string BirthFormatted
|
||||
{
|
||||
get => string.Format(SH.ModelMetadataFetterInfoBirthdayFormat, BirthMonth, BirthDay);
|
||||
get => SH.ModelMetadataFetterInfoBirthdayFormat.Format(BirthMonth, BirthDay);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -20,7 +20,7 @@ internal sealed class AvatarNameCardPicConverter : ValueConverter<Avatar.Avatar?
|
||||
{
|
||||
if (avatar is null)
|
||||
{
|
||||
return null!;
|
||||
return default!;
|
||||
}
|
||||
|
||||
string avatarName = ReplaceSpecialCaseNaming(avatar.Icon["UI_AvatarIcon_".Length..]);
|
||||
|
||||
@@ -5,6 +5,7 @@ using Snap.Hutao.Control;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Model.Metadata.Avatar;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -65,8 +66,8 @@ internal sealed partial class DescriptionsParametersDescriptor : ValueConverter<
|
||||
{
|
||||
if (match.Success)
|
||||
{
|
||||
int index = int.Parse(match.Groups[1].Value) - 1;
|
||||
return ParameterFormat.Format($"{{0:{match.Groups[2].Value}}}", paramList[index]);
|
||||
int index = int.Parse(match.Groups[1].Value, CultureInfo.CurrentCulture) - 1;
|
||||
return ParameterFormat.Format($"{{0:{match.Groups[2].Value}}}", paramList[index], CultureInfo.CurrentCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -114,7 +114,7 @@ internal static class FightPropertyFormat
|
||||
{
|
||||
FormatMethod.Integer => $"{MathF.Round(value, MidpointRounding.AwayFromZero)}",
|
||||
FormatMethod.Percent => $"{value:P1}",
|
||||
_ => value.ToString(),
|
||||
_ => $"{value}",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ internal sealed class ParameterFormat : IFormatProvider, ICustomFormatter
|
||||
/// <param name="str">字符串</param>
|
||||
/// <param name="param">参数</param>
|
||||
/// <returns>格式化的字符串</returns>
|
||||
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;
|
||||
|
||||
@@ -2733,6 +2733,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 请输入正确的邮箱 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewModelHutaoPassportEmailNotValidHint {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewModelHutaoPassportEmailNotValidHint", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 剪贴板中的文本格式不正确 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -824,12 +824,12 @@
|
||||
<data name="ViewDialogDailyNoteNotificationExpeditionNotify" xml:space="preserve">
|
||||
<value>探索派遣完成提醒</value>
|
||||
</data>
|
||||
<data name="ViewDialogDailyNoteNotificationResinNotifyThreshold" xml:space="preserve">
|
||||
<value>原粹树脂提醒阈值</value>
|
||||
</data>
|
||||
<data name="ViewDialogDailyNoteNotificationHomeCoinNotifyThreshold" xml:space="preserve">
|
||||
<value>洞天宝钱提醒阈值</value>
|
||||
</data>
|
||||
<data name="ViewDialogDailyNoteNotificationResinNotifyThreshold" xml:space="preserve">
|
||||
<value>原粹树脂提醒阈值</value>
|
||||
</data>
|
||||
<data name="ViewDialogDailyNoteNotificationShowInHomeWidget" xml:space="preserve">
|
||||
<value>在主页显示卡片</value>
|
||||
</data>
|
||||
@@ -1064,6 +1064,9 @@
|
||||
<data name="ViewModelGachaLogUploadToHutaoCloudProgress" xml:space="preserve">
|
||||
<value>正在上传到胡桃云服务</value>
|
||||
</data>
|
||||
<data name="ViewModelHutaoPassportEmailNotValidHint" xml:space="preserve">
|
||||
<value>请输入正确的邮箱</value>
|
||||
</data>
|
||||
<data name="ViewModelImportFromClipboardErrorTitle" xml:space="preserve">
|
||||
<value>剪贴板中的文本格式不正确</value>
|
||||
</data>
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
<None Remove="Assets\Wide310x150Logo.scale-100.png" />
|
||||
<None Remove="Assets\Wide310x150Logo.scale-200.png" />
|
||||
<None Remove="Assets\Wide310x150Logo.scale-400.png" />
|
||||
<None Remove="CodeMetricsConfig.txt" />
|
||||
<None Remove="Control\Panel\PanelSelector.xaml" />
|
||||
<None Remove="Control\Theme\FontStyle.xaml" />
|
||||
<None Remove="GuideWindow.xaml" />
|
||||
@@ -161,6 +162,7 @@
|
||||
|
||||
<!-- Analyzer Files -->
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="CodeMetricsConfig.txt" />
|
||||
<AdditionalFiles Include="IdentityStructs.json" />
|
||||
<AdditionalFiles Include="NativeMethods.json" />
|
||||
<AdditionalFiles Include="NativeMethods.txt" />
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
<cwc:SettingsCard
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingStorageOpenAction}"
|
||||
Command="{Binding Experimental.OpenDataFolderCommand}"
|
||||
Command="{Binding OpenDataFolderCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingDataFolderDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingDataFolderHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
@@ -168,7 +168,7 @@
|
||||
Margin="0,4,0,0"
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingStorageOpenAction}"
|
||||
Command="{Binding Experimental.OpenCacheFolderCommand}"
|
||||
Command="{Binding OpenCacheFolderCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingCacheFolderDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingCacheFolderHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
@@ -227,7 +227,7 @@
|
||||
Severity="Error"/>
|
||||
<cwc:SettingsCard
|
||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingDangerousAction}"
|
||||
Command="{Binding Experimental.DeleteUsersCommand}"
|
||||
Command="{Binding DeleteUsersCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingDeleteUserDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingDeleteUserHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
using Snap.Hutao.Core;
|
||||
using Snap.Hutao.Factory.Abstraction;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Windows.System;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
/// <summary>
|
||||
/// 实验性功能视图模型
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[ConstructorGenerated]
|
||||
[Injection(InjectAs.Scoped)]
|
||||
internal sealed partial class ExperimentalFeaturesViewModel : ObservableObject
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
|
||||
[Command("OpenCacheFolderCommand")]
|
||||
private Task OpenCacheFolderAsync()
|
||||
{
|
||||
RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
|
||||
return Launcher.LaunchFolderPathAsync(hutaoOptions.LocalCache).AsTask();
|
||||
}
|
||||
|
||||
[Command("OpenDataFolderCommand")]
|
||||
private Task OpenDataFolderAsync()
|
||||
{
|
||||
RuntimeOptions hutaoOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
|
||||
return Launcher.LaunchFolderPathAsync(hutaoOptions.DataFolder).AsTask();
|
||||
}
|
||||
|
||||
[Command("DeleteUsersCommand")]
|
||||
private async Task DangerousDeleteUsersAsync()
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
ContentDialogResult result = await scope.ServiceProvider
|
||||
.GetRequiredService<IContentDialogFactory>()
|
||||
.CreateForConfirmCancelAsync(SH.ViewDialogSettingDeleteUserDataTitle, SH.ViewDialogSettingDeleteUserDataContent)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (result == ContentDialogResult.Primary)
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.Users.ExecuteDeleteAsync().ConfigureAwait(false);
|
||||
|
||||
AppInstance.Restart(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
/// </summary>
|
||||
public string? VerifyCode { get => verifyCode; set => SetProperty(ref verifyCode, value); }
|
||||
|
||||
/// <inheritdoc/>
|
||||
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<IInfoBarService>().Information(response.Message);
|
||||
infoBarService.Information(response.Message);
|
||||
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
serviceProvider.GetRequiredService<HutaoUserOptions>().LoginSucceed(UserName, response.Data);
|
||||
hutaoUserOptions.LoginSucceed(UserName, response.Data);
|
||||
|
||||
await serviceProvider
|
||||
.GetRequiredService<INavigationService>()
|
||||
await navigationService
|
||||
.NavigateAsync<View.Page.SettingPage>(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<IInfoBarService>().Information(response.Message);
|
||||
infoBarService.Information(response.Message);
|
||||
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
serviceProvider.GetRequiredService<HutaoUserOptions>().LoginSucceed(UserName, response.Data);
|
||||
hutaoUserOptions.LoginSucceed(UserName, response.Data);
|
||||
|
||||
await serviceProvider
|
||||
.GetRequiredService<INavigationService>()
|
||||
await navigationService
|
||||
.NavigateAsync<View.Page.SettingPage>(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<IInfoBarService>().Information(response.Message);
|
||||
infoBarService.Information(response.Message);
|
||||
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
serviceProvider.GetRequiredService<HutaoUserOptions>().LoginSucceed(UserName, response.Data);
|
||||
hutaoUserOptions.LoginSucceed(UserName, response.Data);
|
||||
|
||||
await serviceProvider
|
||||
.GetRequiredService<INavigationService>()
|
||||
await navigationService
|
||||
.NavigateAsync<View.Page.SettingPage>(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<IInfoBarService>().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);
|
||||
|
||||
@@ -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<SettingViewModel> logger;
|
||||
private readonly AppOptions options;
|
||||
private readonly RuntimeOptions hutaoOptions;
|
||||
private readonly RuntimeOptions runtimeOptions;
|
||||
private readonly HutaoUserOptions hutaoUserOptions;
|
||||
private readonly ExperimentalFeaturesViewModel experimental;
|
||||
|
||||
private NameValue<BackdropType>? selectedBackdropType;
|
||||
private NameValue<string>? selectedCulture;
|
||||
@@ -54,7 +51,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
/// <summary>
|
||||
/// 胡桃选项
|
||||
/// </summary>
|
||||
public RuntimeOptions HutaoOptions { get => hutaoOptions; }
|
||||
public RuntimeOptions HutaoOptions { get => runtimeOptions; }
|
||||
|
||||
/// <summary>
|
||||
/// 胡桃用户选项
|
||||
@@ -95,11 +92,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实验性功能
|
||||
/// </summary>
|
||||
public ExperimentalFeaturesViewModel Experimental { get => experimental; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task OpenUIAsync()
|
||||
{
|
||||
@@ -216,4 +208,36 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
{
|
||||
serviceProvider.GetRequiredService<INavigationService>().Navigate<View.Page.HutaoPassportPage>(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<IContentDialogFactory>()
|
||||
.CreateForConfirmCancelAsync(SH.ViewDialogSettingDeleteUserDataTitle, SH.ViewDialogSettingDeleteUserDataContent)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (result == ContentDialogResult.Primary)
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.Users.ExecuteDeleteAsync().ConfigureAwait(false);
|
||||
|
||||
AppInstance.Restart(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user