This commit is contained in:
DismissedLight
2024-06-23 19:29:46 +08:00
parent b02f2b47c8
commit ea8685523d
18 changed files with 26 additions and 222 deletions

View File

@@ -18,7 +18,6 @@ using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Service.Navigation;
using Snap.Hutao.ViewModel.Guide;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace Snap.Hutao.Core.LifeCycle;

View File

@@ -21,11 +21,6 @@ internal static class AppInstanceExtension
// Hold the reference here to prevent memory corruption.
private static HANDLE redirectEventHandle;
/// <summary>
/// 同步非阻塞重定向
/// </summary>
/// <param name="appInstance">app实例</param>
/// <param name="args">参数</param>
public static unsafe void RedirectActivationTo(this AppInstance appInstance, AppActivationArguments args)
{
try

View File

@@ -5,117 +5,96 @@ using Windows.Storage;
namespace Snap.Hutao.Core.Setting;
/// <summary>
/// 本地设置
/// </summary>
[HighQuality]
internal static class LocalSetting
{
private static readonly ApplicationDataContainer Container = ApplicationData.Current.LocalSettings;
/// <inheritdoc cref="Get{T}(string, T)"/>
public static byte Get(string key, byte defaultValue)
{
return Get<byte>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static short Get(string key, short defaultValue)
{
return Get<short>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static ushort Get(string key, ushort defaultValue)
{
return Get<ushort>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static int Get(string key, int defaultValue)
{
return Get<int>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static uint Get(string key, uint defaultValue)
{
return Get<uint>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static long Get(string key, long defaultValue)
{
return Get<long>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static ulong Get(string key, ulong defaultValue)
{
return Get<ulong>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static float Get(string key, float defaultValue)
{
return Get<float>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static double Get(string key, double defaultValue)
{
return Get<double>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static bool Get(string key, bool defaultValue)
{
return Get<bool>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static char Get(string key, char defaultValue)
{
return Get<char>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static string Get(string key, string defaultValue)
{
return Get<string>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static DateTimeOffset Get(string key, in DateTimeOffset defaultValue)
{
return Get<DateTimeOffset>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static TimeSpan Get(string key, in TimeSpan defaultValue)
{
return Get<TimeSpan>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static Guid Get(string key, in Guid defaultValue)
{
return Get<Guid>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static Windows.Foundation.Point Get(string key, Windows.Foundation.Point defaultValue)
{
return Get<Windows.Foundation.Point>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static Windows.Foundation.Size Get(string key, Windows.Foundation.Size defaultValue)
{
return Get<Windows.Foundation.Size>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static Windows.Foundation.Rect Get(string key, Windows.Foundation.Rect defaultValue)
{
return Get<Windows.Foundation.Rect>(key, defaultValue);
@@ -126,109 +105,91 @@ internal static class LocalSetting
return Get<ApplicationDataCompositeValue>(key, defaultValue);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, byte value)
{
Set<byte>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, short value)
{
Set<short>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, ushort value)
{
Set<ushort>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, int value)
{
Set<int>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, uint value)
{
Set<uint>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, long value)
{
Set<long>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, ulong value)
{
Set<ulong>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, float value)
{
Set<float>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, double value)
{
Set<double>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, bool value)
{
Set<bool>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, char value)
{
Set<char>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, string value)
{
Set<string>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, in DateTimeOffset value)
{
Set<DateTimeOffset>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, in TimeSpan value)
{
Set<TimeSpan>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, in Guid value)
{
Set<Guid>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, Windows.Foundation.Point value)
{
Set<Windows.Foundation.Point>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, Windows.Foundation.Size value)
{
Set<Windows.Foundation.Size>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, Windows.Foundation.Rect value)
{
Set<Windows.Foundation.Rect>(key, value);

View File

@@ -3,26 +3,11 @@
namespace Snap.Hutao.Core.Threading;
/// <summary>
/// An asynchronous barrier that blocks the signaler until all other participants have signaled.
/// FIFO
/// </summary>
internal class AsyncBarrier
{
/// <summary>
/// The number of participants being synchronized.
/// </summary>
private readonly int participantCount;
/// <summary>
/// The set of participants who have reached the barrier, with their awaiters that can resume those participants.
/// </summary>
private readonly Queue<TaskCompletionSource> waiters;
/// <summary>
/// Initializes a new instance of the <see cref="AsyncBarrier"/> class.
/// </summary>
/// <param name="participants">The number of participants.</param>
public AsyncBarrier(int participants)
{
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(participants, "Participants of AsyncBarrier must be greater than 0");
@@ -33,11 +18,6 @@ internal class AsyncBarrier
waiters = new Queue<TaskCompletionSource>(participants - 1);
}
/// <summary>
/// Signals that a participant is ready, and returns a Task
/// that completes when all other participants have also signaled ready.
/// </summary>
/// <returns>A Task, which will complete (or may already be completed) when the last participant calls this method.</returns>
[SuppressMessage("", "SH007")]
public ValueTask SignalAndWaitAsync()
{

View File

@@ -3,22 +3,17 @@
namespace Snap.Hutao.Core.Threading;
/// <summary>
/// 无区分项的并发<see cref="CancellationTokenSource"/>
/// </summary>
[HighQuality]
[SuppressMessage("", "CA1001")]
internal class ConcurrentCancellationTokenSource
{
private CancellationTokenSource source = new();
/// <summary>
/// 注册取消令牌
/// </summary>
/// <returns>取消令牌</returns>
public CancellationToken Register()
{
source.Cancel();
source.Dispose();
source = new();
return source.Token;
}

View File

@@ -3,7 +3,9 @@
namespace Snap.Hutao.Core.Threading;
#if NET9_0_OR_GREATER
[Obsolete]
#endif
internal readonly struct Delay
{
/// <summary>
@@ -16,14 +18,4 @@ internal readonly struct Delay
{
return Task.Delay((int)(System.Random.Shared.NextDouble() * (max - min)) + min).AsValueTask();
}
public static ValueTask FromSeconds(int seconds)
{
return Task.Delay(TimeSpan.FromSeconds(seconds)).AsValueTask();
}
public static ValueTask FromMilliSeconds(int seconds)
{
return Task.Delay(TimeSpan.FromMilliseconds(seconds)).AsValueTask();
}
}

View File

@@ -6,17 +6,9 @@ using System.Runtime.ExceptionServices;
namespace Snap.Hutao.Core.Threading;
/// <summary>
/// 调度器队列拓展
/// </summary>
[HighQuality]
internal static class DispatcherQueueExtension
{
/// <summary>
/// 在调度器队列同步调用,直到执行结束,会持续阻塞当前线程
/// </summary>
/// <param name="dispatcherQueue">调度器队列</param>
/// <param name="action">执行的回调</param>
public static void Invoke(this DispatcherQueue dispatcherQueue, Action action)
{
if (dispatcherQueue.HasThreadAccess)
@@ -49,13 +41,6 @@ internal static class DispatcherQueueExtension
}
}
/// <summary>
/// 在调度器队列同步调用,直到执行结束,会持续阻塞当前线程
/// </summary>
/// <param name="dispatcherQueue">调度器队列</param>
/// <param name="action">执行的回调</param>
/// <typeparam name="T">返回类型</typeparam>
/// <returns>回调返回值</returns>
public static T Invoke<T>(this DispatcherQueue dispatcherQueue, Func<T> action)
{
T result = default!;

View File

@@ -6,48 +6,35 @@ using Snap.Hutao.Core.Threading.Abstraction;
namespace Snap.Hutao.Core.Threading;
/// <summary>
/// 调度器队列切换操作
/// 等待此类型对象后上下文会被切换至主线程
/// </summary>
[HighQuality]
internal readonly struct DispatcherQueueSwitchOperation : IAwaitable<DispatcherQueueSwitchOperation>, ICriticalAwaiter
{
private readonly DispatcherQueue dispatherQueue;
/// <summary>
/// 构造一个新的调度器队列等待器
/// </summary>
/// <param name="dispatherQueue">调度器队列</param>
public DispatcherQueueSwitchOperation(DispatcherQueue dispatherQueue)
{
this.dispatherQueue = dispatherQueue;
}
/// <inheritdoc/>
public bool IsCompleted
{
get => dispatherQueue.HasThreadAccess;
}
/// <inheritdoc/>
public DispatcherQueueSwitchOperation GetAwaiter()
{
return this;
}
/// <inheritdoc/>
public void GetResult()
{
}
/// <inheritdoc/>
public void OnCompleted(Action continuation)
{
dispatherQueue.TryEnqueue(new DispatcherQueueHandler(continuation));
}
/// <inheritdoc/>
public void UnsafeOnCompleted(Action continuation)
{
using (ExecutionContext.SuppressFlow())

View File

@@ -5,18 +5,12 @@ using Microsoft.UI.Dispatching;
namespace Snap.Hutao.Core.Threading;
/// <summary>
/// 任务上下文
/// </summary>
[Injection(InjectAs.Singleton, typeof(ITaskContext))]
internal sealed class TaskContext : ITaskContext, ITaskContextUnsafe
{
private readonly DispatcherQueueSynchronizationContext synchronizationContext;
private readonly DispatcherQueue dispatcherQueue;
/// <summary>
/// 构造一个新的任务上下文
/// </summary>
public TaskContext()
{
dispatcherQueue = DispatcherQueue.GetForCurrentThread();
@@ -26,25 +20,21 @@ internal sealed class TaskContext : ITaskContext, ITaskContextUnsafe
public DispatcherQueue DispatcherQueue { get => dispatcherQueue; }
/// <inheritdoc/>
public ThreadPoolSwitchOperation SwitchToBackgroundAsync()
{
return new(dispatcherQueue);
}
/// <inheritdoc/>
public DispatcherQueueSwitchOperation SwitchToMainThreadAsync()
{
return new(dispatcherQueue);
}
/// <inheritdoc/>
public void InvokeOnMainThread(Action action)
{
dispatcherQueue.Invoke(action);
}
/// <inheritdoc/>
public T InvokeOnMainThread<T>(Func<T> action)
{
return dispatcherQueue.Invoke(action);

View File

@@ -24,10 +24,6 @@ internal static class TaskExtension
return new(task);
}
/// <summary>
/// 安全的触发任务
/// </summary>
/// <param name="task">任务</param>
public static async void SafeForget(this Task task)
{
try
@@ -54,11 +50,6 @@ internal static class TaskExtension
#endif
}
/// <summary>
/// 安全的触发任务
/// </summary>
/// <param name="task">任务</param>
/// <param name="logger">日志器</param>
public static async void SafeForget(this Task task, ILogger logger)
{
try
@@ -71,16 +62,10 @@ internal static class TaskExtension
}
catch (Exception e)
{
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
}
}
/// <summary>
/// 安全的触发任务
/// </summary>
/// <param name="task">任务</param>
/// <param name="logger">日志器</param>
/// <param name="onException">发生异常时调用</param>
public static async void SafeForget(this Task task, ILogger logger, Action<Exception> onException)
{
try
@@ -93,18 +78,11 @@ internal static class TaskExtension
}
catch (Exception e)
{
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
onException?.Invoke(e);
}
}
/// <summary>
/// 安全的触发任务
/// </summary>
/// <param name="task">任务</param>
/// <param name="logger">日志器</param>
/// <param name="onCanceled">任务取消时调用</param>
/// <param name="onException">发生异常时调用</param>
public static async void SafeForget(this Task task, ILogger logger, Action onCanceled, Action<Exception>? onException = null)
{
try
@@ -117,15 +95,11 @@ internal static class TaskExtension
}
catch (Exception e)
{
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
onException?.Invoke(e);
}
}
/// <summary>
/// 安全的触发任务
/// </summary>
/// <param name="task">任务</param>
public static async void SafeForget(this ValueTask task)
{
try
@@ -152,11 +126,6 @@ internal static class TaskExtension
#endif
}
/// <summary>
/// 安全的触发任务
/// </summary>
/// <param name="task">任务</param>
/// <param name="logger">日志器</param>
public static async void SafeForget(this ValueTask task, ILogger logger)
{
try
@@ -169,16 +138,10 @@ internal static class TaskExtension
}
catch (Exception e)
{
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
}
}
/// <summary>
/// 安全的触发任务
/// </summary>
/// <param name="task">任务</param>
/// <param name="logger">日志器</param>
/// <param name="onException">发生异常时调用</param>
public static async void SafeForget(this ValueTask task, ILogger logger, Action<Exception> onException)
{
try
@@ -191,18 +154,11 @@ internal static class TaskExtension
}
catch (Exception e)
{
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
onException?.Invoke(e);
}
}
/// <summary>
/// 安全的触发任务
/// </summary>
/// <param name="task">任务</param>
/// <param name="logger">日志器</param>
/// <param name="onCanceled">任务取消时调用</param>
/// <param name="onException">发生异常时调用</param>
public static async void SafeForget(this ValueTask task, ILogger logger, Action onCanceled, Action<Exception>? onException = null)
{
try
@@ -215,7 +171,7 @@ internal static class TaskExtension
}
catch (Exception e)
{
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
onException?.Invoke(e);
}
}

View File

@@ -6,49 +6,36 @@ using Snap.Hutao.Core.Threading.Abstraction;
namespace Snap.Hutao.Core.Threading;
/// <summary>
/// 线程池切换操作
/// 等待此类型对象后上下文会被切换至线程池线程
/// </summary>
internal readonly struct ThreadPoolSwitchOperation : IAwaitable<ThreadPoolSwitchOperation>, ICriticalAwaiter
{
private static readonly WaitCallback WaitCallbackRunAction = RunAction;
private readonly DispatcherQueue dispatherQueue;
/// <summary>
/// 构造一个新的线程池切换操作
/// </summary>
/// <param name="dispatherQueue">主线程队列</param>
public ThreadPoolSwitchOperation(DispatcherQueue dispatherQueue)
{
this.dispatherQueue = dispatherQueue;
}
/// <inheritdoc/>
public bool IsCompleted
{
// 如果已经处于后台就不再切换新的线程
get => !dispatherQueue.HasThreadAccess;
}
/// <inheritdoc/>
public ThreadPoolSwitchOperation GetAwaiter()
{
return this;
}
/// <inheritdoc/>
public void GetResult()
{
}
/// <inheritdoc/>
public void OnCompleted(Action continuation)
{
QueueContinuation(continuation, true);
}
/// <inheritdoc/>
public void UnsafeOnCompleted(Action continuation)
{
QueueContinuation(continuation, false);

View File

@@ -5,39 +5,17 @@ using Snap.Hutao.Core.Abstraction;
namespace Snap.Hutao.Core.Threading;
/// <summary>
/// 用于包装异步操作的结果
/// </summary>
/// <typeparam name="TResult">结果类型</typeparam>
/// <typeparam name="TValue">值类型</typeparam>
internal readonly struct ValueResult<TResult, TValue> : IDeconstruct<TResult, TValue>
{
/// <summary>
/// 是否成功
/// </summary>
public readonly TResult IsOk;
/// <summary>
/// 值
/// </summary>
public readonly TValue Value;
/// <summary>
/// 构造一个新的结果
/// </summary>
/// <param name="isOk">是否成功</param>
/// <param name="value">值</param>
public ValueResult(TResult isOk, TValue value)
{
IsOk = isOk;
Value = value;
}
/// <summary>
/// 用于元组析构
/// </summary>
/// <param name="isOk">是否成功</param>
/// <param name="value">值</param>
public void Deconstruct(out TResult isOk, out TValue value)
{
isOk = IsOk;

View File

@@ -3,18 +3,8 @@
namespace Snap.Hutao.Core.Threading;
/// <summary>
/// 结果扩展
/// </summary>
internal static class ValueResultExtension
{
/// <summary>
/// 尝试获取结果的值
/// </summary>
/// <typeparam name="TValue">值的类型</typeparam>
/// <param name="valueResult">结果</param>
/// <param name="value">值</param>
/// <returns>是否获取成功</returns>
public static bool TryGetValue<TValue>(this in ValueResult<bool, TValue> valueResult, [NotNullWhen(true)] out TValue value)
{
value = valueResult.Value;

View File

@@ -33,6 +33,7 @@ internal sealed class HotKeyCombination : ObservableObject
private HOT_KEY_MODIFIERS modifiers;
private VirtualKey key;
private bool isEnabled;
private bool isOn;
[SuppressMessage("", "SH002")]
public HotKeyCombination(IServiceProvider serviceProvider, HWND hwnd, string settingKey, int hotKeyId, HOT_KEY_MODIFIERS defaultModifiers, VirtualKey defaultKey)
@@ -162,6 +163,12 @@ internal sealed class HotKeyCombination : ObservableObject
}
}
public bool IsOn
{
get => isOn;
set => SetProperty(ref isOn, value);
}
public string DisplayName { get => ToString(); }
public bool Register()

View File

@@ -8,6 +8,8 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static Snap.Hutao.Win32.ConstValues;
using static Snap.Hutao.Win32.User32;
using static Snap.Hutao.Win32.Kernel32;
using static Snap.Hutao.Win32.Macros;
namespace Snap.Hutao.Core.Windowing.HotKey;
@@ -39,7 +41,7 @@ internal sealed class HotKeyMessageWindow : IDisposable
if (HWND == default)
{
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(GetLastError()));
}
WindowTable.TryAdd(HWND, this);

View File

@@ -120,19 +120,19 @@ internal sealed partial class HotKeyOptions : ObservableObject, IDisposable
{
lock (syncRoot)
{
if (IsMouseClickRepeatForeverOn)
if (MouseClickRepeatForeverKeyCombination.IsOn)
{
// Turn off
cancellationTokenSource?.Cancel();
cancellationTokenSource = default;
IsMouseClickRepeatForeverOn = false;
MouseClickRepeatForeverKeyCombination.IsOn = false;
}
else
{
// Turn on
cancellationTokenSource = new();
ThreadPool.QueueUserWorkItem(RunMouseClickRepeatForever, cancellationTokenSource.Token);
IsMouseClickRepeatForeverOn = true;
MouseClickRepeatForeverKeyCombination.IsOn = true;
}
}
}

View File

@@ -44,7 +44,7 @@ internal sealed partial class IdentifyMonitorWindow : Window
window.Activate();
}
await Delay.FromSeconds(secondsDelay).ConfigureAwait(true);
await Task.Delay(TimeSpan.FromSeconds(secondsDelay)).ConfigureAwait(true);
foreach (IdentifyMonitorWindow window in windows)
{

View File

@@ -9,10 +9,10 @@ namespace Snap.Hutao.Win32.UI.Input.KeyboardAndMouse;
internal struct INPUT
{
public INPUT_TYPE type;
public AnonymousUnion Anonymous;
public Union Anonymous;
[StructLayout(LayoutKind.Explicit)]
internal struct AnonymousUnion
internal struct Union
{
[FieldOffset(0)]
public MOUSEINPUT mi;