diff --git a/src/Snap.Hutao/Snap.Hutao/App.xaml b/src/Snap.Hutao/Snap.Hutao/App.xaml
index 53814262..ab3ce5f4 100644
--- a/src/Snap.Hutao/Snap.Hutao/App.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/App.xaml
@@ -43,8 +43,8 @@
2
212
- 252
- 252
+ 268
+ 268
https://hut.ao/features/mhy-account-switch.html#%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96-cookie
https://hut.ao/statements/bug-report.html
diff --git a/src/Snap.Hutao/Snap.Hutao/App.xaml.cs b/src/Snap.Hutao/Snap.Hutao/App.xaml.cs
index 45518613..80801cdf 100644
--- a/src/Snap.Hutao/Snap.Hutao/App.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/App.xaml.cs
@@ -3,7 +3,6 @@
using CommunityToolkit.WinUI.Notifications;
using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Media;
using Microsoft.Windows.AppLifecycle;
using Snap.Hutao.Core;
using Snap.Hutao.Core.ExceptionService;
diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Panel/AspectRatio.cs b/src/Snap.Hutao/Snap.Hutao/Control/Panel/AspectRatio.cs
new file mode 100644
index 00000000..71bcf6f1
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Control/Panel/AspectRatio.cs
@@ -0,0 +1,57 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.UI.Xaml;
+using Windows.Foundation;
+
+namespace Snap.Hutao.Control.Panel;
+
+///
+/// 纵横比控件
+///
+internal class AspectRatio : Microsoft.UI.Xaml.Controls.ContentControl
+{
+ private static readonly DependencyProperty TargetWidthProperty = Property.Depend(nameof(TargetWidth), 1D);
+ private static readonly DependencyProperty TargetHeightProperty = Property.Depend(nameof(TargetHeight), 1D);
+
+ ///
+ /// 目标宽度
+ ///
+ public double TargetWidth
+ {
+ get => (double)GetValue(TargetWidthProperty);
+ set => SetValue(TargetWidthProperty, value);
+ }
+
+ ///
+ /// 目标高度
+ ///
+ public double TargetHeight
+ {
+ get => (double)GetValue(TargetHeightProperty);
+ set => SetValue(TargetHeightProperty, value);
+ }
+
+ ///
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ double ratio = TargetWidth / TargetHeight;
+ double ratioAvailable = availableSize.Width / availableSize.Height;
+
+ // 更宽
+ if (ratioAvailable > ratio)
+ {
+ double newWidth = ratio * availableSize.Height;
+ return new Size(newWidth, availableSize.Height);
+ }
+
+ // 更高
+ else if (ratioAvailable < ratio)
+ {
+ double newHeight = availableSize.Width / ratio;
+ return new Size(availableSize.Width, newHeight);
+ }
+
+ return availableSize;
+ }
+}
diff --git a/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs b/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs
index 68466f95..6be2322a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs
@@ -16,7 +16,7 @@ namespace Snap.Hutao.Control;
[SuppressMessage("", "CA1001")]
public class ScopedPage : Page
{
- private readonly CancellationTokenSource viewLoadingCancellationTokenSource = new();
+ private readonly CancellationTokenSource viewCancellationTokenSource = new();
private readonly IServiceScope serviceScope;
///
@@ -37,7 +37,7 @@ public class ScopedPage : Page
where TViewModel : class, IViewModel
{
IViewModel viewModel = serviceScope.ServiceProvider.GetRequiredService();
- viewModel.CancellationToken = viewLoadingCancellationTokenSource.Token;
+ viewModel.CancellationToken = viewCancellationTokenSource.Token;
DataContext = viewModel;
}
@@ -60,10 +60,10 @@ public class ScopedPage : Page
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
base.OnNavigatingFrom(e);
- using (viewLoadingCancellationTokenSource)
+ using (viewCancellationTokenSource)
{
- // Cancel tasks executed by the view model
- viewLoadingCancellationTokenSource.Cancel();
+ // Cancel all tasks executed by the view model
+ viewCancellationTokenSource.Cancel();
IViewModel viewModel = (IViewModel)DataContext;
using (SemaphoreSlim locker = viewModel.DisposeLock)
@@ -79,14 +79,13 @@ public class ScopedPage : Page
}
///
- [SuppressMessage("", "VSTHRD100")]
- protected override async void OnNavigatedTo(NavigationEventArgs e)
+ protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Parameter is INavigationData extra)
{
- await NotifyRecipentAsync(extra).ConfigureAwait(false);
+ NotifyRecipentAsync(extra).SafeForget();
}
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/ISupportAsyncInitialization.cs b/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/ISupportAsyncInitialization.cs
deleted file mode 100644
index 39c3fedb..00000000
--- a/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/ISupportAsyncInitialization.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) DGP Studio. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Snap.Hutao.Core.Abstraction;
-
-///
-/// 可异步初始化
-///
-internal interface ISupportAsyncInitialization
-{
- ///
- /// 是否已经初始化完成
- ///
- public bool IsInitialized { get; }
-
- ///
- /// 异步初始化
- ///
- /// 取消令牌
- /// 初始化任务
- ValueTask InitializeAsync();
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/ISupportValidation.cs b/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/ISupportValidation.cs
deleted file mode 100644
index d2dada6c..00000000
--- a/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/ISupportValidation.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) DGP Studio. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Snap.Hutao.Core.Abstraction;
-
-///
-/// 表示支持验证
-///
-internal interface ISupportValidation
-{
- ///
- /// 验证
- ///
- /// 当前数据是否有效
- public bool Validate();
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs
index 47f85863..41e47120 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs
@@ -25,7 +25,7 @@ public class ImageCache : IImageCache, IImageCacheFilePathOperation
{
private const string CacheFolderName = nameof(ImageCache);
- private static readonly Dictionary RetryCountToDelay = new Dictionary()
+ private static readonly Dictionary RetryCountToDelay = new()
{
[0] = TimeSpan.FromSeconds(4),
[1] = TimeSpan.FromSeconds(16),
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Convert/Md5Convert.cs b/src/Snap.Hutao/Snap.Hutao/Core/Convert.cs
similarity index 80%
rename from src/Snap.Hutao/Snap.Hutao/Core/Convert/Md5Convert.cs
rename to src/Snap.Hutao/Snap.Hutao/Core/Convert.cs
index e20f3c09..3842e83d 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Convert/Md5Convert.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Convert.cs
@@ -4,19 +4,19 @@
using System.Security.Cryptography;
using System.Text;
-namespace Snap.Hutao.Core.Convert;
+namespace Snap.Hutao.Core;
///
/// 支持Md5转换
///
-internal abstract class Md5Convert
+internal static class Convert
{
///
/// 获取字符串的MD5计算结果
///
/// 源字符串
/// 计算的结果
- public static string ToHexString(string source)
+ public static string ToMd5HexString(string source)
{
byte[] hash = MD5.HashData(Encoding.UTF8.GetBytes(source));
return System.Convert.ToHexString(hash);
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs b/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs
index 2b8f6162..92b8293f 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license.
using Microsoft.Win32;
-using Snap.Hutao.Core.Convert;
using Snap.Hutao.Core.Json;
using Snap.Hutao.Extension;
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
@@ -31,7 +30,7 @@ internal static class CoreEnvironment
///
/// 米游社 Rpc 版本
///
- public const string HoyolabXrpcVersion = "2.43.1";
+ public const string HoyolabXrpcVersion = "2.44.1";
///
/// 盐
@@ -39,8 +38,8 @@ internal static class CoreEnvironment
// https://github.com/UIGF-org/Hoyolab.Salt
public static readonly ImmutableDictionary DynamicSecrets = new Dictionary()
{
- [nameof(SaltType.K2)] = "ODzG1Jrn6zebX19VRmaJwjFI2CDvBUGq",
- [nameof(SaltType.LK2)] = "V1PYbXKQY7ysdx3MNCcNbsE1LtY2QZpW",
+ [nameof(SaltType.K2)] = "dZAwGk4e9aC0MXXItkwnHamjA1x30IYw",
+ [nameof(SaltType.LK2)] = "IEIZiKYaput2OCKQprNuGsog1NZc1FkS",
[nameof(SaltType.X4)] = "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs",
[nameof(SaltType.X6)] = "t0qEgfub6cvueAPgR5m9aQWWVciEer7v",
[nameof(SaltType.PROD)] = "JwYDpKvLj6MrMqqYU6jTKF17KNO2PXoS",
@@ -113,7 +112,7 @@ internal static class CoreEnvironment
{
string userName = Environment.UserName;
object? machineGuid = Registry.GetValue(CryptographyKey, MachineGuidValue, userName);
- return Md5Convert.ToHexString($"{userName}{machineGuid}");
+ return Convert.ToMd5HexString($"{userName}{machineGuid}");
}
private static string GetDocumentsHutaoPath()
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs
index f6dd8cfc..33940299 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/PickerExtension.cs
@@ -36,7 +36,7 @@ internal static class PickerExtension
{
Ioc.Default
.GetRequiredService()
- .Warning($"无法打开文件选择器 {exception.Message}");
+ .Warning("无法打开文件选择器", $"请勿在管理员模式下使用此功能 {exception.Message}");
}
return new(false, null!);
@@ -68,7 +68,7 @@ internal static class PickerExtension
{
Ioc.Default
.GetRequiredService()
- .Warning($"无法打开文件选择器 {exception.Message}");
+ .Warning("无法打开文件选择器", $"请勿在管理员模式下使用此功能 {exception.Message}");
}
return new(false, null!);
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 40142bb0..5ddfcc75 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Json/Converter/SeparatorCommaInt32EnumerableConverter.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Json/Converter/SeparatorCommaInt32EnumerableConverter.cs
@@ -11,8 +11,8 @@ internal class SeparatorCommaInt32EnumerableConverter : JsonConverter
public override IEnumerable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
- string? team = reader.GetString();
- IEnumerable? ids = team?.Split(',').Select(x => int.Parse(x));
+ string? source = reader.GetString();
+ IEnumerable? ids = source?.Split(',').Select(int.Parse);
return ids ?? Enumerable.Empty();
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Json/JsonTextEncoder.cs b/src/Snap.Hutao/Snap.Hutao/Core/Json/JsonTextEncoder.cs
index 60c8161d..584e86d5 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Json/JsonTextEncoder.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Json/JsonTextEncoder.cs
@@ -10,6 +10,8 @@ namespace Snap.Hutao.Core.Json;
///
internal class JsonTextEncoder : JavaScriptEncoder
{
+ private static readonly string BackSlashDoubleQuote = "\\\"";
+
///
public override int MaxOutputCharactersPerInputCharacter { get => 6; }
@@ -27,7 +29,7 @@ internal class JsonTextEncoder : JavaScriptEncoder
if (unicodeScalar == '"')
{
numberOfCharactersWritten = 2;
- return "\\\"".AsSpan().TryCopyTo(new Span(buffer, bufferLength));
+ return BackSlashDoubleQuote.AsSpan().TryCopyTo(new Span(buffer, bufferLength));
}
string encoded = $"\\u{(uint)unicodeScalar:x4}";
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/ScheduleTaskHelper.cs b/src/Snap.Hutao/Snap.Hutao/Core/ScheduleTaskHelper.cs
index 8cf91b96..6256358d 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/ScheduleTaskHelper.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/ScheduleTaskHelper.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license.
using Microsoft.Win32.TaskScheduler;
-using System.IO;
using System.Runtime.InteropServices;
using SchedulerTask = Microsoft.Win32.TaskScheduler.Task;
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Threading/CancellationTokenTaskCompletionSource.cs b/src/Snap.Hutao/Snap.Hutao/Core/Threading/CancellationTokenTaskCompletionSource.cs
deleted file mode 100644
index f4e0b5cf..00000000
--- a/src/Snap.Hutao/Snap.Hutao/Core/Threading/CancellationTokenTaskCompletionSource.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) DGP Studio. All rights reserved.
-// Licensed under the MIT license.
-
-namespace Snap.Hutao.Core.Threading;
-
-///
-/// Holds the task for a cancellation token, as well as the token registration. The registration is disposed when this instance is disposed.
-///
-/// 包装类型
-public sealed class CancellationTokenTaskCompletionSource : IDisposable
-{
- ///
- /// The cancellation token registration, if any. This is null if the registration was not necessary.
- ///
- private readonly IDisposable? registration;
-
- ///
- /// Creates a task for the specified cancellation token, registering with the token if necessary.
- ///
- /// The cancellation token to observe.
- public CancellationTokenTaskCompletionSource(CancellationToken cancellationToken)
- {
- if (cancellationToken.IsCancellationRequested)
- {
- Task = Task.CompletedTask;
- return;
- }
-
- TaskCompletionSource tcs = new();
- registration = cancellationToken.Register(() => tcs.TrySetResult(), useSynchronizationContext: false);
- Task = tcs.Task;
- }
-
- ///
- /// Gets the task for the source cancellation token.
- ///
- public Task Task { get; private set; }
-
- ///
- /// Disposes the cancellation token registration, if any. Note that this may cause to never complete.
- ///
- public void Dispose()
- {
- registration?.Dispose();
- }
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatcherQueueExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatcherQueueExtension.cs
index 8210bdc2..07d4e850 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatcherQueueExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Threading/DispatcherQueueExtension.cs
@@ -17,15 +17,13 @@ public static class DispatcherQueueExtension
/// 执行的回调
public static void Invoke(this DispatcherQueue dispatcherQueue, Action action)
{
- using (ManualResetEventSlim blockEvent = new())
+ ManualResetEventSlim blockEvent = new();
+ dispatcherQueue.TryEnqueue(() =>
{
- dispatcherQueue.TryEnqueue(() =>
- {
- action();
- blockEvent.Set();
- });
+ action();
+ blockEvent.Set();
+ });
- blockEvent.Wait();
- }
+ blockEvent.Wait();
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/BackdropType.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/BackdropType.cs
index b4c51158..e4c575ad 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/BackdropType.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/BackdropType.cs
@@ -11,7 +11,7 @@ public enum BackdropType
///
/// 无
///
- None = 0,
+ None,
///
/// 亚克力
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs
index dc0053f0..d84e756d 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs
@@ -148,6 +148,7 @@ internal sealed class ExtendedWindow : IRecipient();
messenger.Register(this);
messenger.Register(this);
+
window.Closed += OnWindowClosed;
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/BinaryReaderExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/BinaryReaderExtension.cs
deleted file mode 100644
index 606477ff..00000000
--- a/src/Snap.Hutao/Snap.Hutao/Extension/BinaryReaderExtension.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) DGP Studio. All rights reserved.
-// Licensed under the MIT license.
-
-using System.IO;
-
-namespace Snap.Hutao.Extension;
-
-///
-/// 扩展
-///
-public static class BinaryReaderExtension
-{
- ///
- /// 判断是否处于流的结尾
- ///
- /// 读取器
- /// 是否处于流的结尾
- public static bool EndOfStream(this BinaryReader reader)
- {
- return reader.BaseStream.Position >= reader.BaseStream.Length;
- }
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/DateTimeOffsetExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/DateTimeOffsetExtension.cs
index 8c0188a7..f939b0d2 100644
--- a/src/Snap.Hutao/Snap.Hutao/Extension/DateTimeOffsetExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/DateTimeOffsetExtension.cs
@@ -18,7 +18,7 @@ public static class DateTimeOffsetExtension
{
if (keepTicks)
{
- dateTimeOffset += TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now).Negate();
+ dateTimeOffset -= TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now);
}
return dateTimeOffset.ToLocalTime();
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.List.cs b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.List.cs
index a8cfb3c0..0e39ba3c 100644
--- a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.List.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.List.cs
@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Snap.Hutao.Extension;
@@ -37,6 +38,7 @@ public static partial class EnumerableExtension
/// 源类型
/// 源
/// 源列表或空列表
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static List EmptyIfNull(this List? source)
{
return source ?? new();
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/LoggerExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/LoggerExtension.cs
index ba27babf..4db7cc49 100644
--- a/src/Snap.Hutao/Snap.Hutao/Extension/LoggerExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/LoggerExtension.cs
@@ -9,13 +9,6 @@ namespace Snap.Hutao.Extension;
[SuppressMessage("", "CA2254")]
public static class LoggerExtension
{
- ///
- public static T LogInformation(this ILogger logger, string message, params object?[] param)
- {
- logger.LogInformation(message, param);
- return default!;
- }
-
///
public static T LogWarning(this ILogger logger, string message, params object?[] param)
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/NumberExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/NumberExtension.cs
index 8046cb24..50bc6e56 100644
--- a/src/Snap.Hutao/Snap.Hutao/Extension/NumberExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/NumberExtension.cs
@@ -1,6 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using System.Runtime.CompilerServices;
+
namespace Snap.Hutao.Extension;
///
@@ -8,36 +10,15 @@ namespace Snap.Hutao.Extension;
///
public static class NumberExtension
{
- ///
- /// 获取从右向左某位上的数字
- ///
- /// 源
- /// 位
- /// 数字
- public static int AtPlace(this int x, int place)
- {
- return (int)(x / Math.Pow(10, place - 1)) % 10;
- }
-
///
/// 计算给定整数的位数
///
/// 给定的整数
/// 位数
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Place(this int x)
{
// Benchmarked and compared as a most optimized solution
return (int)(MathF.Log10(x) + 1);
}
-
- ///
- /// 计算给定整数的位数
- ///
- /// 给定的整数
- /// 位数
- public static int Place(this long x)
- {
- // Benchmarked and compared as a most optimized solution
- return (int)(MathF.Log10(x) + 1);
- }
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/Abstraction/IAsyncRelayCommandFactory.cs b/src/Snap.Hutao/Snap.Hutao/Factory/Abstraction/IAsyncRelayCommandFactory.cs
deleted file mode 100644
index 02f2469e..00000000
--- a/src/Snap.Hutao/Snap.Hutao/Factory/Abstraction/IAsyncRelayCommandFactory.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) DGP Studio. All rights reserved.
-// Licensed under the MIT license.
-
-using CommunityToolkit.Mvvm.Input;
-
-namespace Snap.Hutao.Factory.Abstraction;
-
-///
-/// Factory for creating with additional processing.
-///
-public interface IAsyncRelayCommandFactory
-{
- ///
- /// Create a reference to AsyncRelayCommand.
- ///
- /// The cancelable execution logic.
- /// AsyncRelayCommand.
- AsyncRelayCommand Create(Func cancelableExecute);
-
- ///
- /// Create a reference to AsyncRelayCommand.
- ///
- /// The cancelable execution logic.
- /// The execution status logic.
- /// AsyncRelayCommand.
- AsyncRelayCommand Create(Func cancelableExecute, Func canExecute);
-
- ///
- /// Create a reference to AsyncRelayCommand.
- ///
- /// The execution logic.
- /// AsyncRelayCommand.
- AsyncRelayCommand Create(Func execute);
-
- ///
- /// Create a reference to AsyncRelayCommand.
- ///
- /// The execution logic.
- /// The execution status logic.
- /// AsyncRelayCommand.
- AsyncRelayCommand Create(Func execute, Func canExecute);
-
- ///
- /// Create a reference to AsyncRelayCommand.
- ///
- /// The type of the command parameter.
- /// The cancelable execution logic.
- /// AsyncRelayCommand.
- AsyncRelayCommand Create(Func cancelableExecute);
-
- ///
- /// Create a reference to AsyncRelayCommand.
- ///
- /// The type of the command parameter.
- /// The cancelable execution logic.
- /// The execution status logic.
- /// AsyncRelayCommand.
- AsyncRelayCommand Create(Func cancelableExecute, Predicate canExecute);
-
- ///
- /// Create a reference to AsyncRelayCommand.
- ///
- /// The type of the command parameter.
- /// The execution logic.
- /// AsyncRelayCommand.
- AsyncRelayCommand Create(Func execute);
-
- ///
- /// Create a reference to AsyncRelayCommand.
- ///
- /// The type of the command parameter.
- /// The execution logic.
- /// The execution status logic.
- /// AsyncRelayCommand.
- AsyncRelayCommand Create(Func execute, Predicate canExecute);
-}
diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/AsyncRelayCommandFactory.cs b/src/Snap.Hutao/Snap.Hutao/Factory/AsyncRelayCommandFactory.cs
deleted file mode 100644
index 45c0c591..00000000
--- a/src/Snap.Hutao/Snap.Hutao/Factory/AsyncRelayCommandFactory.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) DGP Studio. All rights reserved.
-// Licensed under the MIT license.
-
-using CommunityToolkit.Mvvm.Input;
-using Snap.Hutao.Core.Logging;
-using Snap.Hutao.Factory.Abstraction;
-
-namespace Snap.Hutao.Factory;
-
-///
-[Injection(InjectAs.Transient, typeof(IAsyncRelayCommandFactory))]
-internal class AsyncRelayCommandFactory : IAsyncRelayCommandFactory
-{
- private readonly ILogger logger;
-
- ///
- /// 构造一个新的异步命令工厂
- ///
- /// 日志器
- public AsyncRelayCommandFactory(ILogger logger)
- {
- this.logger = logger;
- }
-
- ///
- public AsyncRelayCommand Create(Func execute)
- {
- return Register(new AsyncRelayCommand(execute));
- }
-
- ///
- public AsyncRelayCommand Create(Func cancelableExecute)
- {
- return Register(new AsyncRelayCommand(cancelableExecute));
- }
-
- ///
- public AsyncRelayCommand Create(Func execute, Predicate canExecute)
- {
- return Register(new AsyncRelayCommand(execute, canExecute));
- }
-
- ///
- public AsyncRelayCommand Create(Func cancelableExecute, Predicate canExecute)
- {
- return Register(new AsyncRelayCommand(cancelableExecute, canExecute));
- }
-
- ///
- public AsyncRelayCommand Create(Func execute)
- {
- return Register(new AsyncRelayCommand(execute));
- }
-
- ///
- public AsyncRelayCommand Create(Func cancelableExecute)
- {
- return Register(new AsyncRelayCommand(cancelableExecute));
- }
-
- ///
- public AsyncRelayCommand Create(Func execute, Func canExecute)
- {
- return Register(new AsyncRelayCommand(execute, canExecute));
- }
-
- ///
- public AsyncRelayCommand Create(Func cancelableExecute, Func canExecute)
- {
- return Register(new AsyncRelayCommand(cancelableExecute, canExecute));
- }
-
- private AsyncRelayCommand Register(AsyncRelayCommand command)
- {
- ReportException(command);
- return command;
- }
-
- private AsyncRelayCommand Register(AsyncRelayCommand command)
- {
- ReportException(command);
- return command;
- }
-
- private void ReportException(IAsyncRelayCommand command)
- {
- command.PropertyChanged += (sender, args) =>
- {
- if (sender is IAsyncRelayCommand asyncRelayCommand)
- {
- if (args.PropertyName == nameof(AsyncRelayCommand.ExecutionTask))
- {
- if (asyncRelayCommand.ExecutionTask?.Exception is AggregateException exception)
- {
- Exception baseException = exception.GetBaseException();
- logger.LogError(EventIds.AsyncCommandException, baseException, "{name} Exception", nameof(AsyncRelayCommand));
- }
- }
- }
- };
- }
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Costume.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Costume.cs
index 49721a6e..538106a0 100644
--- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Costume.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Costume.cs
@@ -31,10 +31,10 @@ public class Costume
///
/// 图标
///
- public string? Icon { get; set; }
+ public string Icon { get; set; } = default!;
///
/// 侧面图标
///
- public string? SideIcon { get; set; }
+ public string SideIcon { get; set; } = default!;
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/AvatarIds.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/AvatarIds.cs
index 61bf3544..37551378 100644
--- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/AvatarIds.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/AvatarIds.cs
@@ -97,8 +97,18 @@ public static class AvatarIds
{
return new(idAvatarMap)
{
- [PlayerBoy] = new() { Name = "旅行者", Icon = "UI_AvatarIcon_PlayerBoy", Quality = Intrinsic.ItemQuality.QUALITY_ORANGE },
- [PlayerGirl] = new() { Name = "旅行者", Icon = "UI_AvatarIcon_PlayerGirl", Quality = Intrinsic.ItemQuality.QUALITY_ORANGE },
+ [PlayerBoy] = new()
+ {
+ Name = "旅行者",
+ Icon = "UI_AvatarIcon_PlayerBoy",
+ Quality = Intrinsic.ItemQuality.QUALITY_ORANGE,
+ },
+ [PlayerGirl] = new()
+ {
+ Name = "旅行者",
+ Icon = "UI_AvatarIcon_PlayerGirl",
+ Quality = Intrinsic.ItemQuality.QUALITY_ORANGE,
+ },
};
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs
index b9bb62e6..d19a31b5 100644
--- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs
@@ -34,6 +34,8 @@ internal class ElementNameIconConverter : ValueConverter
return string.IsNullOrEmpty(element)
? Web.HutaoEndpoints.UIIconNone
: new Uri(Web.HutaoEndpoints.StaticFile("IconElement", $"UI_Icon_Element_{element}.png"));
+
+ // $"UI_Icon_Element_{element}.png"
}
///
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/ReliquaryWeightConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/ReliquaryWeightConfiguration.cs
index ce96c436..7e9e54c0 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/ReliquaryWeightConfiguration.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/ReliquaryWeightConfiguration.cs
@@ -6,7 +6,7 @@ using Snap.Hutao.Model.Metadata;
namespace Snap.Hutao.Service.AvatarInfo.Factory;
///
-/// 权重配置
+/// 圣遗物评分权重配置
///
internal static partial class ReliquaryWeightConfiguration
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs
index 56de2214..bafb9562 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/AvatarInfo/Factory/SummaryAvatarFactory.cs
@@ -45,28 +45,53 @@ internal class SummaryAvatarFactory
PropertyAvatar propertyAvatar = new()
{
+ // metadata part
Id = avatar.Id,
Name = avatar.Name,
- Icon = AvatarIconConverter.IconNameToUri(avatar.Icon),
- SideIcon = AvatarIconConverter.IconNameToUri(avatar.SideIcon),
NameCard = AvatarNameCardPicConverter.AvatarToUri(avatar),
Quality = avatar.Quality,
Element = ElementNameIconConverter.ElementNameToElementType(avatar.FetterInfo.VisionBefore),
- FetterLevel = avatarInfo.FetterInfo.ExpLevel,
- Weapon = reliquaryAndWeapon.Weapon,
- Reliquaries = reliquaryAndWeapon.Reliquaries,
+
+ // webinfo & metadata mixed part
Constellations = SummaryHelper.CreateConstellations(avatarInfo.TalentIdList, avatar.SkillDepot.Talents),
Skills = SummaryHelper.CreateSkills(avatarInfo.SkillLevelMap, avatarInfo.ProudSkillExtraLevelMap, avatar.SkillDepot.GetCompositeSkillsNoInherents()),
+
+ // webinfo part
+ FetterLevel = avatarInfo.FetterInfo?.ExpLevel ?? 0,
Properties = SummaryHelper.CreateAvatarProperties(avatarInfo.FightPropMap),
- Score = reliquaryAndWeapon.Reliquaries.Sum(r => r.Score).ToString("F2"),
CritScore = $"{SummaryHelper.ScoreCrit(avatarInfo.FightPropMap):F2}",
LevelNumber = int.Parse(avatarInfo.PropMap?[PlayerProperty.PROP_LEVEL].Value ?? string.Empty),
+
+ // processed webinfo part
+ Weapon = reliquaryAndWeapon.Weapon,
+ Reliquaries = reliquaryAndWeapon.Reliquaries,
+ Score = reliquaryAndWeapon.Reliquaries.Sum(r => r.Score).ToString("F2"),
};
+ TryApplyCostumeIconToAvatar(ref propertyAvatar, avatar);
+
propertyAvatar.Level = $"Lv.{propertyAvatar.LevelNumber}";
return propertyAvatar;
}
+ private void TryApplyCostumeIconToAvatar(ref PropertyAvatar propertyAvatar, MetadataAvatar avatar)
+ {
+ // Set to costume icon
+ if (avatarInfo.CostumeId.HasValue)
+ {
+ int costumeId = avatarInfo.CostumeId.Value;
+ Model.Metadata.Avatar.Costume costume = avatar.Costumes.Single(c => c.Id == costumeId);
+
+ propertyAvatar.Icon = AvatarIconConverter.IconNameToUri(costume.Icon);
+ propertyAvatar.SideIcon = AvatarIconConverter.IconNameToUri(costume.SideIcon);
+ }
+ else
+ {
+ propertyAvatar.Icon = AvatarIconConverter.IconNameToUri(avatar.Icon);
+ propertyAvatar.SideIcon = AvatarIconConverter.IconNameToUri(avatar.SideIcon);
+ }
+ }
+
private ReliquaryAndWeapon ProcessEquip(List equipments)
{
List reliquaryList = new();
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs
index 507d3d4f..3030a31f 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs
@@ -1,7 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
-using Microsoft.Win32.SafeHandles;
using Snap.Hutao.Core.Diagnostics;
using Snap.Hutao.Win32;
using System.Diagnostics;
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs
index 56fd454d..91a57941 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license.
using Microsoft.Extensions.Caching.Memory;
-using Snap.Hutao.Core.Abstraction;
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Core.Diagnostics;
using Snap.Hutao.Core.Logging;
@@ -20,7 +19,7 @@ namespace Snap.Hutao.Service.Metadata;
///
[Injection(InjectAs.Singleton, typeof(IMetadataService))]
[HttpClient(HttpClientConfigration.Default)]
-internal partial class MetadataService : IMetadataService, IMetadataInitializer, ISupportAsyncInitialization
+internal partial class MetadataService : IMetadataService, IMetadataInitializer
{
private const string MetaFileName = "Meta.json";
@@ -63,14 +62,11 @@ internal partial class MetadataService : IMetadataService, IMetadataInitializer,
Directory.CreateDirectory(metadataFolderPath);
}
- ///
- public bool IsInitialized { get => isInitialized; private set => isInitialized = value; }
-
///
public async ValueTask InitializeAsync()
{
await initializeCompletionSource.Task.ConfigureAwait(false);
- return IsInitialized;
+ return isInitialized;
}
///
@@ -79,7 +75,7 @@ internal partial class MetadataService : IMetadataService, IMetadataInitializer,
ValueStopwatch stopwatch = ValueStopwatch.StartNew();
logger.LogInformation(EventIds.MetadataInitialization, "Metadata initializaion begin");
- IsInitialized = await TryUpdateMetadataAsync(token).ConfigureAwait(false);
+ isInitialized = await TryUpdateMetadataAsync(token).ConfigureAwait(false);
initializeCompletionSource.SetResult();
logger.LogInformation(EventIds.MetadataInitialization, "Metadata initializaion completed in {time}ms", stopwatch.GetElapsedTime().TotalMilliseconds);
@@ -186,7 +182,7 @@ internal partial class MetadataService : IMetadataService, IMetadataInitializer,
private async ValueTask FromCacheOrFileAsync(string fileName, CancellationToken token)
where T : class
{
- Verify.Operation(IsInitialized, "元数据服务尚未初始化,或初始化失败");
+ Verify.Operation(isInitialized, "元数据服务尚未初始化,或初始化失败");
string cacheKey = $"{nameof(MetadataService)}.Cache.{fileName}";
if (memoryCache.TryGetValue(cacheKey, out object? value))
@@ -204,7 +200,6 @@ internal partial class MetadataService : IMetadataService, IMetadataInitializer,
private async ValueTask> FromCacheAsDictionaryAsync(string fileName, Func keySelector, CancellationToken token)
where TKey : notnull
{
- Verify.Operation(IsInitialized, "元数据服务尚未初始化,或初始化失败");
string cacheKey = $"{nameof(MetadataService)}.Cache.{fileName}.Map.{typeof(TKey).Name}";
if (memoryCache.TryGetValue(cacheKey, out object? value))
@@ -218,9 +213,8 @@ internal partial class MetadataService : IMetadataService, IMetadataInitializer,
}
private async ValueTask> FromCacheAsDictionaryAsync(string fileName, Func keySelector, Func valueSelector, CancellationToken token)
- where TKey : notnull
+ where TKey : notnull
{
- Verify.Operation(IsInitialized, "元数据服务尚未初始化,或初始化失败");
string cacheKey = $"{nameof(MetadataService)}.Cache.{fileName}.Map.{typeof(TKey).Name}.{typeof(TValue).Name}";
if (memoryCache.TryGetValue(cacheKey, out object? value))
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs b/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs
index 759094c6..2f51b46a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs
@@ -97,8 +97,15 @@ internal class UserService : IUserService
await ThreadHelper.SwitchToBackgroundAsync();
using (IServiceScope scope = scopeFactory.CreateScope())
{
- // Note: cascade deleted dailynotes
- await scope.ServiceProvider.GetRequiredService().Users.RemoveAndSaveAsync(user.Entity).ConfigureAwait(false);
+ try
+ {
+ // Note: cascade deleted dailynotes
+ await scope.ServiceProvider.GetRequiredService().Users.RemoveAndSaveAsync(user.Entity).ConfigureAwait(false);
+ }
+ catch (DbUpdateConcurrencyException ex)
+ {
+ throw new Core.ExceptionService.UserdataCorruptedException("用户已被其他功能删除", ex);
+ }
}
messenger.Send(new UserRemovedMessage(user.Entity));
diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
index abe0a59b..6b5ffe17 100644
--- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
+++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
@@ -154,7 +154,7 @@
-
+
@@ -182,7 +182,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementContentPage.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementContentPage.xaml.cs
index 8094f9da..eed60ae4 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementContentPage.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementContentPage.xaml.cs
@@ -6,8 +6,6 @@ using Microsoft.UI.Xaml.Navigation;
using Microsoft.Web.WebView2.Core;
using Snap.Hutao.Core;
using Snap.Hutao.Service.Navigation;
-using Snap.Hutao.View.Extension;
-using System.Diagnostics;
using Windows.System;
namespace Snap.Hutao.View.Page;
@@ -69,7 +67,8 @@ public sealed partial class AnnouncementContentPage : Microsoft.UI.Xaml.Controls
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
- //WebView.CoreWebView2.Environment.Exit();
+
+ // WebView.CoreWebView2.Environment.Exit();
}
private static string? ReplaceForeground(string? rawContent, ElementTheme theme)
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml
index e14257c0..bfbbea10 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml
@@ -9,6 +9,7 @@
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shci="using:Snap.Hutao.Control.Image"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
+ xmlns:shcp="using:Snap.Hutao.Control.Panel"
xmlns:shv="using:Snap.Hutao.ViewModel"
xmlns:shvc="using:Snap.Hutao.View.Control"
xmlns:wsc="using:WinUICommunity.SettingsUI.Controls"
@@ -219,16 +220,18 @@
-
-
+ Style="{StaticResource BorderCardStyle}">
+
+
+
+
成就服务
/// 信息条服务
/// Json序列化选项
- /// 异步命令工厂
/// 内容对话框工厂
/// 消息器
public AchievementViewModel(
@@ -65,7 +64,6 @@ internal class AchievementViewModel : Abstraction.ViewModel, INavigationRecipien
IAchievementService achievementService,
IInfoBarService infoBarService,
JsonSerializerOptions options,
- IAsyncRelayCommandFactory asyncRelayCommandFactory,
IContentDialogFactory contentDialogFactory,
IMessenger messenger)
{
@@ -75,12 +73,12 @@ internal class AchievementViewModel : Abstraction.ViewModel, INavigationRecipien
this.contentDialogFactory = contentDialogFactory;
this.options = options;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
- ImportUIAFFromClipboardCommand = asyncRelayCommandFactory.Create(ImportUIAFFromClipboardAsync);
- ImportUIAFFromFileCommand = asyncRelayCommandFactory.Create(ImportUIAFFromFileAsync);
- ExportAsUIAFToFileCommand = asyncRelayCommandFactory.Create(ExportAsUIAFToFileAsync);
- AddArchiveCommand = asyncRelayCommandFactory.Create(AddArchiveAsync);
- RemoveArchiveCommand = asyncRelayCommandFactory.Create(RemoveArchiveAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
+ ImportUIAFFromClipboardCommand = new AsyncRelayCommand(ImportUIAFFromClipboardAsync);
+ ImportUIAFFromFileCommand = new AsyncRelayCommand(ImportUIAFFromFileAsync);
+ ExportAsUIAFToFileCommand = new AsyncRelayCommand(ExportAsUIAFToFileAsync);
+ AddArchiveCommand = new AsyncRelayCommand(AddArchiveAsync);
+ RemoveArchiveCommand = new AsyncRelayCommand(RemoveArchiveAsync);
SearchAchievementCommand = new RelayCommand(SearchAchievement);
SortIncompletedSwitchCommand = new RelayCommand(UpdateAchievementsSort);
SaveAchievementCommand = new RelayCommand(SaveAchievement);
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AnnouncementViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AnnouncementViewModel.cs
index d1946821..d3562c4b 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AnnouncementViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AnnouncementViewModel.cs
@@ -3,7 +3,6 @@
using CommunityToolkit.Mvvm.Input;
using Snap.Hutao.Core;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.Navigation;
using Snap.Hutao.View.Page;
@@ -25,15 +24,11 @@ internal class AnnouncementViewModel : Abstraction.ViewModel
/// 构造一个公告视图模型
///
/// 公告服务
- /// 导航服务
- /// 异步命令工厂
- /// 信息条服务
- /// 日志器
- public AnnouncementViewModel(IAnnouncementService announcementService, IAsyncRelayCommandFactory asyncRelayCommandFactory)
+ public AnnouncementViewModel(IAnnouncementService announcementService)
{
this.announcementService = announcementService;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
OpenAnnouncementUICommand = new RelayCommand(OpenAnnouncementUI);
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarPropertyViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarPropertyViewModel.cs
index 7245feae..13706a31 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarPropertyViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarPropertyViewModel.cs
@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Imaging;
@@ -51,13 +52,11 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel
/// 用户服务
/// 角色信息服务
/// 对话框工厂
- /// 异步命令工厂
/// 信息条服务
public AvatarPropertyViewModel(
IUserService userService,
IAvatarInfoService avatarInfoService,
IContentDialogFactory contentDialogFactory,
- IAsyncRelayCommandFactory asyncRelayCommandFactory,
IInfoBarService infoBarService)
{
this.userService = userService;
@@ -65,12 +64,12 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel
this.infoBarService = infoBarService;
this.contentDialogFactory = contentDialogFactory;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
- RefreshFromEnkaApiCommand = asyncRelayCommandFactory.Create(RefreshByEnkaApiAsync);
- RefreshFromHoyolabGameRecordCommand = asyncRelayCommandFactory.Create(RefreshByHoyolabGameRecordAsync);
- RefreshFromHoyolabCalculateCommand = asyncRelayCommandFactory.Create(RefreshByHoyolabCalculateAsync);
- ExportAsImageCommand = asyncRelayCommandFactory.Create(ExportAsImageAsync);
- CultivateCommand = asyncRelayCommandFactory.Create(CultivateAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
+ RefreshFromEnkaApiCommand = new AsyncRelayCommand(RefreshByEnkaApiAsync);
+ RefreshFromHoyolabGameRecordCommand = new AsyncRelayCommand(RefreshByHoyolabGameRecordAsync);
+ RefreshFromHoyolabCalculateCommand = new AsyncRelayCommand(RefreshByHoyolabCalculateAsync);
+ ExportAsImageCommand = new AsyncRelayCommand(ExportAsImageAsync);
+ CultivateCommand = new AsyncRelayCommand(CultivateAsync);
}
///
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/CultivationViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/CultivationViewModel.cs
index 25381245..5b2d2994 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/CultivationViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/CultivationViewModel.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.Input;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model.Binding.Cultivation;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction;
@@ -36,13 +35,11 @@ internal class CultivationViewModel : Abstraction.ViewModel
///
/// 养成服务
/// 信息服务
- /// 异步命令工厂
/// 元数据服务
/// 日志器
public CultivationViewModel(
ICultivationService cultivationService,
IInfoBarService infoBarService,
- IAsyncRelayCommandFactory asyncRelayCommandFactory,
IMetadataService metadataService,
ILogger logger)
{
@@ -51,12 +48,12 @@ internal class CultivationViewModel : Abstraction.ViewModel
this.metadataService = metadataService;
this.logger = logger;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
- AddProjectCommand = asyncRelayCommandFactory.Create(AddProjectAsync);
- RemoveProjectCommand = asyncRelayCommandFactory.Create(RemoveProjectAsync);
- RemoveEntryCommand = asyncRelayCommandFactory.Create(RemoveEntryAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
+ AddProjectCommand = new AsyncRelayCommand(AddProjectAsync);
+ RemoveProjectCommand = new AsyncRelayCommand(RemoveProjectAsync);
+ RemoveEntryCommand = new AsyncRelayCommand(RemoveEntryAsync);
SaveInventoryItemCommand = new RelayCommand(SaveInventoryItem);
- UpdateStatisticsItemsCommand = asyncRelayCommandFactory.Create(UpdateStatisticsItemsAsync);
+ UpdateStatisticsItemsCommand = new AsyncRelayCommand(UpdateStatisticsItemsAsync);
NavigateToPageCommand = new RelayCommand(NavigateToPage);
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs
index 2eff3677..7c8d8d49 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs
@@ -4,7 +4,6 @@
using CommunityToolkit.Mvvm.Input;
using Snap.Hutao.Core;
using Snap.Hutao.Core.Database;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model;
using Snap.Hutao.Model.Binding.User;
using Snap.Hutao.Model.Entity;
@@ -52,23 +51,21 @@ internal class DailyNoteViewModel : Abstraction.ViewModel
/// 用户服务
/// 实时便笺服务
/// 数据库上下文
- /// 异步命令工厂
public DailyNoteViewModel(
IUserService userService,
IDailyNoteService dailyNoteService,
- AppDbContext appDbContext,
- IAsyncRelayCommandFactory asyncRelayCommandFactory)
+ AppDbContext appDbContext)
{
this.userService = userService;
this.dailyNoteService = dailyNoteService;
this.appDbContext = appDbContext;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
- TrackRoleCommand = asyncRelayCommandFactory.Create(TrackRoleAsync);
- RefreshCommand = asyncRelayCommandFactory.Create(RefreshAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
+ TrackRoleCommand = new AsyncRelayCommand(TrackRoleAsync);
+ RefreshCommand = new AsyncRelayCommand(RefreshAsync);
RemoveDailyNoteCommand = new RelayCommand(RemoveDailyNote);
- ModifyNotificationCommand = asyncRelayCommandFactory.Create(ModifyDailyNoteNotificationAsync);
- DailyNoteVerificationCommand = asyncRelayCommandFactory.Create(VerifyDailyNoteVerificationAsync);
+ ModifyNotificationCommand = new AsyncRelayCommand(ModifyDailyNoteNotificationAsync);
+ DailyNoteVerificationCommand = new AsyncRelayCommand(VerifyDailyNoteVerificationAsync);
}
///
@@ -176,7 +173,16 @@ internal class DailyNoteViewModel : Abstraction.ViewModel
private async Task OpenUIAsync()
{
- UserAndUids = await userService.GetRoleCollectionAsync().ConfigureAwait(false);
+ try
+ {
+ UserAndUids = await userService.GetRoleCollectionAsync().ConfigureAwait(false);
+ }
+ catch (Core.ExceptionService.UserdataCorruptedException ex)
+ {
+ Ioc.Default.GetRequiredService().Error(ex);
+ return;
+ }
+
try
{
ThrowIfViewDisposed();
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs
index 3cb28db5..a754c227 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/ExperimentalFeaturesViewModel.cs
@@ -5,7 +5,6 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model.Entity.Database;
using Snap.Hutao.Service.Abstraction;
using Windows.Storage;
@@ -22,12 +21,11 @@ internal class ExperimentalFeaturesViewModel : ObservableObject
///
/// 构造一个新的实验性功能视图模型
///
- /// 异步命令工厂
- public ExperimentalFeaturesViewModel(IAsyncRelayCommandFactory asyncRelayCommandFactory)
+ public ExperimentalFeaturesViewModel()
{
- OpenCacheFolderCommand = asyncRelayCommandFactory.Create(OpenCacheFolderAsync);
- OpenDataFolderCommand = asyncRelayCommandFactory.Create(OpenDataFolderAsync);
- DeleteUsersCommand = asyncRelayCommandFactory.Create(DangerousDeleteUsersAsync);
+ OpenCacheFolderCommand = new AsyncRelayCommand(OpenCacheFolderAsync);
+ OpenDataFolderCommand = new AsyncRelayCommand(OpenDataFolderAsync);
+ DeleteUsersCommand = new AsyncRelayCommand(DangerousDeleteUsersAsync);
DeleteAllScheduleTasksCommand = new RelayCommand(DangerousDeleteAllScheduleTasks);
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLogViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLogViewModel.cs
index 9e1280e1..07ab21bf 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLogViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLogViewModel.cs
@@ -1,7 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
-using Microsoft.Data.Sqlite;
+using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Extension;
using Snap.Hutao.Core.IO;
@@ -41,14 +41,12 @@ internal class GachaLogViewModel : Abstraction.ViewModel
/// 祈愿记录服务
/// 信息
/// Json序列化选项
- /// 异步命令工厂
/// 内容对话框工厂
/// 文件选择器工厂
public GachaLogViewModel(
IGachaLogService gachaLogService,
IInfoBarService infoBarService,
JsonSerializerOptions options,
- IAsyncRelayCommandFactory asyncRelayCommandFactory,
IContentDialogFactory contentDialogFactory,
IPickerFactory pickerFactory)
{
@@ -58,13 +56,13 @@ internal class GachaLogViewModel : Abstraction.ViewModel
this.contentDialogFactory = contentDialogFactory;
this.options = options;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
- RefreshByWebCacheCommand = asyncRelayCommandFactory.Create(RefreshByWebCacheAsync);
- RefreshByStokenCommand = asyncRelayCommandFactory.Create(RefreshByStokenAsync);
- RefreshByManualInputCommand = asyncRelayCommandFactory.Create(RefreshByManualInputAsync);
- ImportFromUIGFJsonCommand = asyncRelayCommandFactory.Create(ImportFromUIGFJsonAsync);
- ExportToUIGFJsonCommand = asyncRelayCommandFactory.Create(ExportToUIGFJsonAsync);
- RemoveArchiveCommand = asyncRelayCommandFactory.Create(RemoveArchiveAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
+ RefreshByWebCacheCommand = new AsyncRelayCommand(RefreshByWebCacheAsync);
+ RefreshByStokenCommand = new AsyncRelayCommand(RefreshByStokenAsync);
+ RefreshByManualInputCommand = new AsyncRelayCommand(RefreshByManualInputAsync);
+ ImportFromUIGFJsonCommand = new AsyncRelayCommand(ImportFromUIGFJsonAsync);
+ ExportToUIGFJsonCommand = new AsyncRelayCommand(ExportToUIGFJsonAsync);
+ RemoveArchiveCommand = new AsyncRelayCommand(RemoveArchiveAsync);
}
///
@@ -202,24 +200,27 @@ internal class GachaLogViewModel : Abstraction.ViewModel
Progress progress = new(dialog.OnReport);
bool authkeyValid;
- using (await DisposeLock.EnterAsync().ConfigureAwait(false))
+ try
{
- try
+ using (await DisposeLock.EnterAsync().ConfigureAwait(false))
{
- authkeyValid = await gachaLogService.RefreshGachaLogAsync(query, strategy, progress, CancellationToken).ConfigureAwait(false);
- }
- catch (OperationCanceledException)
- {
- // We set true here in order to hide the dialog.
- authkeyValid = true;
- infoBarService.Warning("祈愿记录刷新操作被异常取消");
- }
- catch (Core.ExceptionService.UserdataCorruptedException ex)
- {
- authkeyValid = false;
- infoBarService.Error(ex);
+ try
+ {
+ authkeyValid = await gachaLogService.RefreshGachaLogAsync(query, strategy, progress, CancellationToken).ConfigureAwait(false);
+ }
+ catch (Core.ExceptionService.UserdataCorruptedException ex)
+ {
+ authkeyValid = false;
+ infoBarService.Error(ex);
+ }
}
}
+ catch (OperationCanceledException)
+ {
+ // We set true here in order to hide the dialog.
+ authkeyValid = true;
+ infoBarService.Warning("祈愿记录刷新操作被异常取消");
+ }
await ThreadHelper.SwitchToMainThreadAsync();
if (authkeyValid)
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoDatabaseViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoDatabaseViewModel.cs
index 3414b98b..f5fa0da4 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoDatabaseViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/HutaoDatabaseViewModel.cs
@@ -1,7 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
-using Snap.Hutao.Factory.Abstraction;
+using CommunityToolkit.Mvvm.Input;
using Snap.Hutao.Model.Binding.Hutao;
using Snap.Hutao.Service.Hutao;
using Snap.Hutao.Web.Hutao.Model;
@@ -26,12 +26,11 @@ internal class HutaoDatabaseViewModel : Abstraction.ViewModel
/// 构造一个新的胡桃数据库视图模型
///
/// 胡桃服务缓存
- /// 异步命令工厂
- public HutaoDatabaseViewModel(IHutaoCache hutaoCache, IAsyncRelayCommandFactory asyncRelayCommandFactory)
+ public HutaoDatabaseViewModel(IHutaoCache hutaoCache)
{
this.hutaoCache = hutaoCache;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
}
///
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/LaunchGameViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/LaunchGameViewModel.cs
index 56d066bf..7598df05 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/LaunchGameViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/LaunchGameViewModel.cs
@@ -6,7 +6,6 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Snap.Hutao.Core.Database;
using Snap.Hutao.Core.LifeCycle;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model.Binding.LaunchGame;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.Entity.Database;
@@ -62,22 +61,20 @@ internal class LaunchGameViewModel : Abstraction.ViewModel
/// 游戏服务
/// 内存缓存
/// 数据库上下文
- /// 异步命令工厂
public LaunchGameViewModel(
IGameService gameService,
IMemoryCache memoryCache,
- AppDbContext appDbContext,
- IAsyncRelayCommandFactory asyncRelayCommandFactory)
+ AppDbContext appDbContext)
{
this.gameService = gameService;
this.appDbContext = appDbContext;
this.memoryCache = memoryCache;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
- LaunchCommand = asyncRelayCommandFactory.Create(LaunchAsync);
- DetectGameAccountCommand = asyncRelayCommandFactory.Create(DetectGameAccountAsync);
- ModifyGameAccountCommand = asyncRelayCommandFactory.Create(ModifyGameAccountAsync);
- RemoveGameAccountCommand = asyncRelayCommandFactory.Create(RemoveGameAccountAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
+ LaunchCommand = new AsyncRelayCommand(LaunchAsync);
+ DetectGameAccountCommand = new AsyncRelayCommand(DetectGameAccountAsync);
+ ModifyGameAccountCommand = new AsyncRelayCommand(ModifyGameAccountAsync);
+ RemoveGameAccountCommand = new AsyncRelayCommand(RemoveGameAccountAsync);
AttachGameAccountCommand = new RelayCommand(AttachGameAccountToCurrentUserGameRole);
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs
index a455fa40..db6c7bc4 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs
@@ -5,7 +5,6 @@ using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Snap.Hutao.Core.Database;
using Snap.Hutao.Core.Windowing;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.Entity.Database;
@@ -45,13 +44,11 @@ internal class SettingViewModel : Abstraction.ViewModel
///
/// 数据库上下文
/// 游戏服务
- /// 异步命令工厂
/// 实验性功能
/// 日志器
public SettingViewModel(
AppDbContext appDbContext,
IGameService gameService,
- IAsyncRelayCommandFactory asyncRelayCommandFactory,
ExperimentalFeaturesViewModel experimental,
ILogger logger)
{
@@ -73,10 +70,10 @@ internal class SettingViewModel : Abstraction.ViewModel
GamePath = gameService.GetGamePathSkipLocator();
- SetGamePathCommand = asyncRelayCommandFactory.Create(SetGamePathAsync);
- DebugExceptionCommand = asyncRelayCommandFactory.Create(DebugThrowExceptionAsync);
+ SetGamePathCommand = new AsyncRelayCommand(SetGamePathAsync);
+ DebugExceptionCommand = new AsyncRelayCommand(DebugThrowExceptionAsync);
DeleteGameWebCacheCommand = new RelayCommand(DeleteGameWebCache);
- ShowSignInWebViewDialogCommand = asyncRelayCommandFactory.Create(ShowSignInWebViewDialogAsync);
+ ShowSignInWebViewDialogCommand = new AsyncRelayCommand(ShowSignInWebViewDialogAsync);
}
///
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyssRecordViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyssRecordViewModel.cs
index ecb7d1a6..71003861 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyssRecordViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/SpiralAbyssRecordViewModel.cs
@@ -1,8 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Message;
using Snap.Hutao.Model.Binding.SpiralAbyss;
using Snap.Hutao.Model.Binding.User;
@@ -40,22 +40,20 @@ internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient深渊记录服务
/// 元数据服务
/// 用户服务
- /// 异步命令工厂
/// 消息器
public SpiralAbyssRecordViewModel(
ISpiralAbyssRecordService spiralAbyssRecordService,
IMetadataService metadataService,
IUserService userService,
- IAsyncRelayCommandFactory asyncRelayCommandFactory,
IMessenger messenger)
{
this.spiralAbyssRecordService = spiralAbyssRecordService;
this.metadataService = metadataService;
this.userService = userService;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
- RefreshCommand = asyncRelayCommandFactory.Create(RefreshAsync);
- UploadSpiralAbyssRecordCommand = asyncRelayCommandFactory.Create(UploadSpiralAbyssRecordAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
+ RefreshCommand = new AsyncRelayCommand(RefreshAsync);
+ UploadSpiralAbyssRecordCommand = new AsyncRelayCommand(UploadSpiralAbyssRecordAsync);
messenger.Register(this);
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/TestViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/TestViewModel.cs
index a8790ebe..c19b1385 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/TestViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/TestViewModel.cs
@@ -1,10 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using CommunityToolkit.Mvvm.Input;
using Snap.Hutao.Core.IO;
using Snap.Hutao.Core.IO.Bits;
-using Snap.Hutao.Extension;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Service.User;
using Snap.Hutao.View.Dialog;
using Snap.Hutao.Web.Hoyolab;
@@ -22,13 +21,12 @@ internal class TestViewModel : Abstraction.ViewModel
///
/// 构造一个新的测试视图模型
///
- /// 异步命令工厂
- public TestViewModel(IAsyncRelayCommandFactory asyncRelayCommandFactory)
+ public TestViewModel()
{
- ShowCommunityGameRecordDialogCommand = asyncRelayCommandFactory.Create(ShowCommunityGameRecordDialogAsync);
- ShowAdoptCalculatorDialogCommand = asyncRelayCommandFactory.Create(ShowAdoptCalculatorDialogAsync);
- DangerousLoginMihoyoBbsCommand = asyncRelayCommandFactory.Create(DangerousLoginMihoyoBbsAsync);
- DownloadStaticFileCommand = asyncRelayCommandFactory.Create(DownloadStaticFileAsync);
+ ShowCommunityGameRecordDialogCommand = new AsyncRelayCommand(ShowCommunityGameRecordDialogAsync);
+ ShowAdoptCalculatorDialogCommand = new AsyncRelayCommand(ShowAdoptCalculatorDialogAsync);
+ DangerousLoginMihoyoBbsCommand = new AsyncRelayCommand(DangerousLoginMihoyoBbsAsync);
+ DownloadStaticFileCommand = new AsyncRelayCommand(DownloadStaticFileAsync);
}
///
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/UserViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/UserViewModel.cs
index 7d2268c6..20f8fb82 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/UserViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/UserViewModel.cs
@@ -3,10 +3,9 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
-using Microsoft.Data.Sqlite;
+using Snap.Hutao.Core.ExceptionService;
using Snap.Hutao.Core.IO.DataTransfer;
using Snap.Hutao.Extension;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model.Binding.User;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.Navigation;
@@ -36,16 +35,15 @@ internal class UserViewModel : ObservableObject
///
/// 用户服务
/// 信息条服务
- /// 异步命令工厂
- public UserViewModel(IUserService userService, IInfoBarService infoBarService, IAsyncRelayCommandFactory asyncRelayCommandFactory)
+ public UserViewModel(IUserService userService, IInfoBarService infoBarService)
{
this.userService = userService;
this.infoBarService = infoBarService;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
- AddUserCommand = asyncRelayCommandFactory.Create(AddUserAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
+ AddUserCommand = new AsyncRelayCommand(AddUserAsync);
LoginMihoyoUserCommand = new RelayCommand(LoginMihoyoUser);
- RemoveUserCommand = asyncRelayCommandFactory.Create(RemoveUserAsync);
+ RemoveUserCommand = new AsyncRelayCommand(RemoveUserAsync);
CopyCookieCommand = new RelayCommand(CopyCookie);
}
@@ -106,10 +104,9 @@ internal class UserViewModel : ObservableObject
Users = await userService.GetUserCollectionAsync().ConfigureAwait(true);
SelectedUser = userService.Current;
}
- catch (SqliteException ex)
+ catch (UserdataCorruptedException ex)
{
- // SQLite Error 11: 'database disk image is malformed'.
- infoBarService.Error(ex, "用户数据文件已损坏");
+ infoBarService.Error(ex);
}
}
@@ -168,9 +165,18 @@ internal class UserViewModel : ObservableObject
private async Task RemoveUserAsync(User? user)
{
- Verify.Operation(user != null, "待删除的用户不应为 null");
- await userService.RemoveUserAsync(user).ConfigureAwait(false);
- infoBarService.Success($"用户 [{user.UserInfo?.Nickname}] 成功移除");
+ if (user != null)
+ {
+ try
+ {
+ await userService.RemoveUserAsync(user!).ConfigureAwait(false);
+ infoBarService.Success($"用户 [{user.UserInfo?.Nickname}] 成功移除");
+ }
+ catch (UserdataCorruptedException ex)
+ {
+ infoBarService.Error(ex);
+ }
+ }
}
private void CopyCookie(User? user)
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs
index 2619b9ee..350d6c51 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/WelcomeViewModel.cs
@@ -3,6 +3,7 @@
using CommunityToolkit.Common;
using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.WinUI.Notifications;
using Microsoft.Extensions.DependencyInjection;
@@ -11,7 +12,6 @@ using Snap.Hutao.Core.IO;
using Snap.Hutao.Core.IO.Bits;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Extension;
-using Snap.Hutao.Factory.Abstraction;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.Compression;
@@ -32,12 +32,11 @@ internal class WelcomeViewModel : ObservableObject
///
/// 构造一个新的欢迎视图模型
///
- /// 异步命令工厂
/// 服务提供器
- public WelcomeViewModel(IAsyncRelayCommandFactory asyncRelayCommandFactory, IServiceProvider serviceProvider)
+ public WelcomeViewModel(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
}
///
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs
index 36c56cbe..c74329fd 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs
@@ -5,7 +5,6 @@ using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.WinUI.UI;
using Microsoft.Extensions.Primitives;
using Snap.Hutao.Extension;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model.Binding.Cultivation;
using Snap.Hutao.Model.Binding.Hutao;
using Snap.Hutao.Model.Intrinsic;
@@ -46,13 +45,12 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel
///
/// 元数据服务
/// 胡桃缓存
- /// 异步命令工厂
- public WikiAvatarViewModel(IMetadataService metadataService, IHutaoCache hutaoCache, IAsyncRelayCommandFactory asyncRelayCommandFactory)
+ public WikiAvatarViewModel(IMetadataService metadataService, IHutaoCache hutaoCache)
{
this.metadataService = metadataService;
this.hutaoCache = hutaoCache;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
- CultivateCommand = asyncRelayCommandFactory.Create(CultivateAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
+ CultivateCommand = new AsyncRelayCommand(CultivateAsync);
FilterCommand = new RelayCommand(ApplyFilter);
}
@@ -199,7 +197,7 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel
private static bool DoFilter(string input, Avatar avatar)
{
- bool keep = false;
+ bool keep = true;
foreach (StringSegment segment in new StringTokenizer(input, ' '.Enumerate().ToArray()))
{
@@ -207,31 +205,31 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel
if (value == "火" || value == "水" || value == "草" || value == "雷" || value == "冰" || value == "风" || value == "岩")
{
- keep = keep || avatar.FetterInfo.VisionBefore == value;
+ keep = keep && avatar.FetterInfo.VisionBefore == value;
continue;
}
if (IntrinsicImmutables.AssociationTypes.Contains(value))
{
- keep = keep || avatar.FetterInfo.Association.GetDescriptionOrNull() == value;
+ keep = keep && avatar.FetterInfo.Association.GetDescriptionOrNull() == value;
continue;
}
if (IntrinsicImmutables.WeaponTypes.Contains(value))
{
- keep = keep || avatar.Weapon.GetDescriptionOrNull() == value;
+ keep = keep && avatar.Weapon.GetDescriptionOrNull() == value;
continue;
}
if (IntrinsicImmutables.ItemQualities.Contains(value))
{
- keep = keep || avatar.Quality.GetDescriptionOrNull() == value;
+ keep = keep && avatar.Quality.GetDescriptionOrNull() == value;
continue;
}
if (IntrinsicImmutables.BodyTypes.Contains(value))
{
- keep = keep || avatar.Body.GetDescriptionOrNull() == value;
+ keep = keep && avatar.Body.GetDescriptionOrNull() == value;
continue;
}
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs
index 38ab890b..0b503f9b 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/WikiWeaponViewModel.cs
@@ -5,7 +5,6 @@ using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.WinUI.UI;
using Microsoft.Extensions.Primitives;
using Snap.Hutao.Extension;
-using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model.Binding.Cultivation;
using Snap.Hutao.Model.Binding.Hutao;
using Snap.Hutao.Model.Intrinsic;
@@ -49,14 +48,13 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
///
/// 元数据服务
/// 胡桃缓存
- /// 异步命令工厂
- public WikiWeaponViewModel(IMetadataService metadataService, IHutaoCache hutaoCache, IAsyncRelayCommandFactory asyncRelayCommandFactory)
+ public WikiWeaponViewModel(IMetadataService metadataService, IHutaoCache hutaoCache)
{
this.metadataService = metadataService;
this.hutaoCache = hutaoCache;
- OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
- CultivateCommand = asyncRelayCommandFactory.Create(CultivateAsync);
+ OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
+ CultivateCommand = new AsyncRelayCommand(CultivateAsync);
FilterCommand = new RelayCommand(ApplyFilter);
}
@@ -197,7 +195,7 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
private static bool DoFilter(string input, Weapon weapon)
{
- bool keep = false;
+ bool keep = true;
foreach (StringSegment segment in new StringTokenizer(input, ' '.Enumerate().ToArray()))
{
@@ -205,19 +203,19 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
if (IntrinsicImmutables.WeaponTypes.Contains(value))
{
- keep = keep || weapon.WeaponType.GetDescriptionOrNull() == value;
+ keep = keep && weapon.WeaponType.GetDescriptionOrNull() == value;
continue;
}
if (IntrinsicImmutables.ItemQualities.Contains(value))
{
- keep = keep || weapon.Quality.GetDescriptionOrNull() == value;
+ keep = keep && weapon.Quality.GetDescriptionOrNull() == value;
continue;
}
if (IntrinsicImmutables.FightProperties.Contains(value))
{
- keep = keep || weapon.Property.Properties.ElementAtOrDefault(1).GetDescriptionOrNull() == value;
+ keep = keep && weapon.Property.Properties.ElementAtOrDefault(1).GetDescriptionOrNull() == value;
continue;
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs
index 639b8b23..7d6ed485 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs
@@ -3,7 +3,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Web.WebView2.Core;
-using Snap.Hutao.Core.Convert;
using Snap.Hutao.Core.Database;
using Snap.Hutao.Extension;
using Snap.Hutao.Model.Binding.User;
@@ -125,7 +124,7 @@ public class MiHoYoJSInterface
string salt = Core.CoreEnvironment.DynamicSecrets[nameof(SaltType.LK2)];
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
string r = GetRandomString();
- string check = Md5Convert.ToHexString($"salt={salt}&t={t}&r={r}").ToLowerInvariant();
+ string check = Core.Convert.ToMd5HexString($"salt={salt}&t={t}&r={r}").ToLowerInvariant();
return new() { Data = new() { ["DS"] = $"{t},{r},{check}", }, };
@@ -157,7 +156,7 @@ public class MiHoYoJSInterface
int r = GetRandom();
string b = param.Payload.Body;
string q = param.Payload.GetQueryParam();
- string check = Md5Convert.ToHexString($"salt={salt}&t={t}&r={r}&b={b}&q={q}").ToLowerInvariant();
+ string check = Core.Convert.ToMd5HexString($"salt={salt}&t={t}&r={r}&b={b}&q={q}").ToLowerInvariant();
return new() { Data = new() { ["DS"] = $"{t},{r},{check}" } };
@@ -257,8 +256,9 @@ public class MiHoYoJSInterface
return new() { Data = new() { ["statusBarHeight"] = 0 } };
}
- public virtual IJsResult? PushPage(JsParam param)
+ public virtual async Task PushPageAsync(JsParam param)
{
+ await ThreadHelper.SwitchToMainThreadAsync();
webView.Navigate(param.Payload.Page);
return null;
}
@@ -370,7 +370,7 @@ public class MiHoYoJSInterface
"getUserInfo" => GetUserInfo(param),
"hideLoading" => null,
"login" => null,
- "pushPage" => PushPage(param),
+ "pushPage" => await PushPageAsync(param).ConfigureAwait(false),
"showLoading" => null,
_ => logger.LogWarning("Unhandled Message Type: {method}", param.Method),
};
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/DynamicSecret/DynamicSecretHandler.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/DynamicSecret/DynamicSecretHandler.cs
index a6ae0b79..65007186 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/DynamicSecret/DynamicSecretHandler.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/DynamicSecret/DynamicSecretHandler.cs
@@ -1,7 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
-using Snap.Hutao.Core.Convert;
using Snap.Hutao.Web.Request;
using System.Net.Http;
using System.Text;
@@ -46,7 +45,7 @@ public class DynamicSecretHandler : DelegatingHandler
dsContent = $"{dsContent}&b={b}&q={q}";
}
- string check = Md5Convert.ToHexString(dsContent).ToLowerInvariant();
+ string check = Core.Convert.ToMd5HexString(dsContent).ToLowerInvariant();
request.Headers.Remove("DS-Option");
request.Headers.Set("DS", $"{t},{r},{check}");
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaClient.cs
index 02ea534b..8071e744 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaClient.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaClient.cs
@@ -11,7 +11,6 @@ using Snap.Hutao.Web.Hutao.Model;
using Snap.Hutao.Web.Hutao.Model.Post;
using Snap.Hutao.Web.Response;
using System.Net.Http;
-using System.Net.Http.Json;
namespace Snap.Hutao.Web.Hutao;
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Response/Response.cs b/src/Snap.Hutao/Snap.Hutao/Web/Response/Response.cs
index c554ebc3..dc78eb9e 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Response/Response.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Response/Response.cs
@@ -1,7 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
-using Snap.Hutao.Core.Abstraction;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Web.Bridge.Model;
@@ -10,7 +9,7 @@ namespace Snap.Hutao.Web.Response;
///
/// 提供 的非泛型基类
///
-public class Response : ISupportValidation
+public class Response
{
///
/// 构造一个新的响应
@@ -64,12 +63,6 @@ public class Response : ISupportValidation
return response ?? new(0x26F19335, message, default);
}
- ///
- public bool Validate()
- {
- return Enum.IsDefined(typeof(KnownReturnCode), ReturnCode);
- }
-
///
public override string ToString()
{