mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
refine discord controller
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Snap.Hutao.Core.Threading;
|
namespace Snap.Hutao.Core.Threading;
|
||||||
|
|
||||||
internal delegate bool SpinWaitPredicate<T>(ref readonly T state);
|
internal delegate bool SpinWaitPredicate<T>(ref readonly T state);
|
||||||
@@ -15,4 +17,23 @@ internal static class SpinWaitPolyfill
|
|||||||
spinner.SpinOnce();
|
spinner.SpinOnce();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("", "SH002")]
|
||||||
|
public static unsafe bool SpinUntil<T>(ref T state, delegate*<ref readonly T, bool> condition, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
long startTime = Stopwatch.GetTimestamp();
|
||||||
|
|
||||||
|
SpinWait spinner = default;
|
||||||
|
while (!condition(ref state))
|
||||||
|
{
|
||||||
|
spinner.SpinOnce();
|
||||||
|
|
||||||
|
if (timeout < Stopwatch.GetElapsedTime(startTime))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"Snap.Hutao": {
|
"Snap.Hutao": {
|
||||||
"commandName": "MsixPackage",
|
"commandName": "MsixPackage",
|
||||||
"nativeDebugging": false,
|
"nativeDebugging": true,
|
||||||
"doNotLaunchApp": false,
|
"doNotLaunchApp": false,
|
||||||
"allowLocalNetworkLoopbackProperty": true
|
"allowLocalNetworkLoopbackProperty": true
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,32 +7,15 @@ using System.Collections.ObjectModel;
|
|||||||
|
|
||||||
namespace Snap.Hutao.Service.DailyNote;
|
namespace Snap.Hutao.Service.DailyNote;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 实时便笺服务
|
|
||||||
/// </summary>
|
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal interface IDailyNoteService
|
internal interface IDailyNoteService
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 添加实时便笺
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userAndUid">角色</param>
|
|
||||||
/// <returns>任务</returns>
|
|
||||||
ValueTask AddDailyNoteAsync(UserAndUid userAndUid, CancellationToken token = default);
|
ValueTask AddDailyNoteAsync(UserAndUid userAndUid, CancellationToken token = default);
|
||||||
|
|
||||||
ValueTask<ObservableCollection<DailyNoteEntry>> GetDailyNoteEntryCollectionAsync(bool forceRefresh = false, CancellationToken token = default);
|
ValueTask<ObservableCollection<DailyNoteEntry>> GetDailyNoteEntryCollectionAsync(bool forceRefresh = false, CancellationToken token = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 异步刷新实时便笺
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>任务</returns>
|
|
||||||
ValueTask RefreshDailyNotesAsync(CancellationToken token = default);
|
ValueTask RefreshDailyNotesAsync(CancellationToken token = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 移除指定的实时便笺
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="entry">指定的实时便笺</param>
|
|
||||||
/// <returns>任务</returns>
|
|
||||||
ValueTask RemoveDailyNoteAsync(DailyNoteEntry entry, CancellationToken token = default);
|
ValueTask RemoveDailyNoteAsync(DailyNoteEntry entry, CancellationToken token = default);
|
||||||
|
|
||||||
ValueTask UpdateDailyNoteAsync(DailyNoteEntry entry, CancellationToken token = default);
|
ValueTask UpdateDailyNoteAsync(DailyNoteEntry entry, CancellationToken token = default);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ internal static class DiscordController
|
|||||||
|
|
||||||
private static long currentClientId;
|
private static long currentClientId;
|
||||||
private static unsafe IDiscordCore* discordCorePtr;
|
private static unsafe IDiscordCore* discordCorePtr;
|
||||||
private static bool isInitialized;
|
private static bool isCallbackInitialized;
|
||||||
|
|
||||||
public static async ValueTask<DiscordResult> SetDefaultActivityAsync(DateTimeOffset startTime)
|
public static async ValueTask<DiscordResult> SetDefaultActivityAsync(DateTimeOffset startTime)
|
||||||
{
|
{
|
||||||
@@ -108,7 +108,7 @@ internal static class DiscordController
|
|||||||
|
|
||||||
public static unsafe void Stop()
|
public static unsafe void Stop()
|
||||||
{
|
{
|
||||||
if (!isInitialized)
|
if (!isCallbackInitialized)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -147,13 +147,13 @@ internal static class DiscordController
|
|||||||
discordCorePtr->set_log_hook(discordCorePtr, DiscordLogLevel.Debug, default, &DebugWriteDiscordMessage);
|
discordCorePtr->set_log_hook(discordCorePtr, DiscordLogLevel.Debug, default, &DebugWriteDiscordMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInitialized)
|
if (isCallbackInitialized)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiscordRunCallbacksAsync(StopTokenSource.Token).SafeForget();
|
DiscordRunCallbacksAsync(StopTokenSource.Token).SafeForget();
|
||||||
isInitialized = true;
|
isCallbackInitialized = true;
|
||||||
|
|
||||||
[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
|
[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
|
||||||
static unsafe void DebugWriteDiscordMessage(void* state, DiscordLogLevel logLevel, sbyte* ptr)
|
static unsafe void DebugWriteDiscordMessage(void* state, DiscordLogLevel logLevel, sbyte* ptr)
|
||||||
@@ -183,7 +183,7 @@ internal static class DiscordController
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DiscordResult result = DiscordCoreRunRunCallbacks();
|
DiscordResult result = RunDiscordCoreRunCallbacks();
|
||||||
if (result is not DiscordResult.Ok)
|
if (result is not DiscordResult.Ok)
|
||||||
{
|
{
|
||||||
if (result is DiscordResult.NotRunning)
|
if (result is DiscordResult.NotRunning)
|
||||||
@@ -200,11 +200,11 @@ internal static class DiscordController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SEHException ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Known error codes:
|
// Known error codes:
|
||||||
// 0x80004005 E_FAIL
|
// 0x80004005 E_FAIL
|
||||||
System.Diagnostics.Debug.WriteLine($"[Discord.GameSDK ERROR]:0x{ex.ErrorCode:X}");
|
System.Diagnostics.Debug.WriteLine($"[Discord.GameSDK ERROR]:0x{ex.HResult:X}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ internal static class DiscordController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe DiscordResult DiscordCoreRunRunCallbacks()
|
unsafe DiscordResult RunDiscordCoreRunCallbacks()
|
||||||
{
|
{
|
||||||
if (discordCorePtr is not null)
|
if (discordCorePtr is not null)
|
||||||
{
|
{
|
||||||
@@ -253,6 +253,7 @@ internal static class DiscordController
|
|||||||
public DiscordUpdateActivityAsyncAction(IDiscordActivityManager* activityManagerPtr)
|
public DiscordUpdateActivityAsyncAction(IDiscordActivityManager* activityManagerPtr)
|
||||||
{
|
{
|
||||||
this.activityManagerPtr = activityManagerPtr;
|
this.activityManagerPtr = activityManagerPtr;
|
||||||
|
discordAsyncAction.Result = (DiscordResult)(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DiscordResult WaitUpdateActivity(DiscordActivity activity)
|
public DiscordResult WaitUpdateActivity(DiscordActivity activity)
|
||||||
@@ -262,7 +263,7 @@ internal static class DiscordController
|
|||||||
activityManagerPtr->update_activity(activityManagerPtr, &activity, actionPtr, &HandleResult);
|
activityManagerPtr->update_activity(activityManagerPtr, &activity, actionPtr, &HandleResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpinWaitPolyfill.SpinUntil(ref discordAsyncAction, &CheckActionCompleted);
|
SpinWaitPolyfill.SpinUntil(ref discordAsyncAction, &CheckActionCompleted, TimeSpan.FromSeconds(5));
|
||||||
return discordAsyncAction.Result;
|
return discordAsyncAction.Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,15 @@ internal sealed partial class DiscordService : IDiscordService, IDisposable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Process process in discordProcesses)
|
foreach (ref readonly Process process in discordProcesses.AsSpan())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (string.Equals(process.MainWindowTitle, "Discord Updater", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
_ = process.Handle;
|
_ = process.Handle;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
|
|||||||
Reference in New Issue
Block a user