mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Compare commits
49 Commits
1.7.13
...
winappsdk-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
957b63ac32 | ||
|
|
3af8f356cc | ||
|
|
05608cee30 | ||
|
|
f8d7f72679 | ||
|
|
1564f2a97e | ||
|
|
1f5619baa0 | ||
|
|
7406f5822f | ||
|
|
38cffe4dc3 | ||
|
|
ba4a7c1447 | ||
|
|
a03edeef3f | ||
|
|
981d2d74ee | ||
|
|
27aa404e52 | ||
|
|
78a56ec912 | ||
|
|
8f25769527 | ||
|
|
85e31d122d | ||
|
|
65191d91bd | ||
|
|
c885a6f220 | ||
|
|
3d0ea2dd4e | ||
|
|
9d2e5896e6 | ||
|
|
d376d9b3f6 | ||
|
|
449ae4499b | ||
|
|
2d59fcfb21 | ||
|
|
5600d1fe9e | ||
|
|
02ee082bd0 | ||
|
|
f4a1914735 | ||
|
|
df8f317020 | ||
|
|
d09e4c3035 | ||
|
|
e0d43b0dfb | ||
|
|
805d8ed87d | ||
|
|
bbbe2eeb79 | ||
|
|
7b8cc1b4c3 | ||
|
|
7c357d3a1c | ||
|
|
7fc4e1a0a3 | ||
|
|
f29fa1e8a0 | ||
|
|
9a54463d7d | ||
|
|
ababf74473 | ||
|
|
ba7ba3af44 | ||
|
|
91f6665849 | ||
|
|
154f6a1bb6 | ||
|
|
45cca2185e | ||
|
|
95631df4fa | ||
|
|
d8186082bf | ||
|
|
18d6ee214c | ||
|
|
bfc967d244 | ||
|
|
0c8f757d69 | ||
|
|
dda4e60813 | ||
|
|
cc01269d9a | ||
|
|
b5706c316f | ||
|
|
bc0e2bd717 |
@@ -52,8 +52,8 @@ public sealed partial class App : Application
|
|||||||
if (firstInstance.IsCurrent)
|
if (firstInstance.IsCurrent)
|
||||||
{
|
{
|
||||||
// manually invoke
|
// manually invoke
|
||||||
activation.NonRedirectToActivate(firstInstance, activatedEventArgs);
|
|
||||||
activation.InitializeWith(firstInstance);
|
activation.InitializeWith(firstInstance);
|
||||||
|
activation.NonRedirectToActivate(firstInstance, activatedEventArgs);
|
||||||
|
|
||||||
LogDiagnosticInformation();
|
LogDiagnosticInformation();
|
||||||
serviceProvider.GetRequiredService<IJumpListInterop>().ConfigureAsync().SafeForget();
|
serviceProvider.GetRequiredService<IJumpListInterop>().ConfigureAsync().SafeForget();
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// 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 CommunityToolkit.WinUI.Notifications;
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Windows.AppLifecycle;
|
using Microsoft.Windows.AppLifecycle;
|
||||||
|
using Microsoft.Windows.AppNotifications;
|
||||||
using Snap.Hutao.Core.Setting;
|
using Snap.Hutao.Core.Setting;
|
||||||
using Snap.Hutao.Service.DailyNote;
|
using Snap.Hutao.Service.DailyNote;
|
||||||
using Snap.Hutao.Service.Hutao;
|
using Snap.Hutao.Service.Hutao;
|
||||||
@@ -23,24 +23,9 @@ namespace Snap.Hutao.Core.LifeCycle;
|
|||||||
[SuppressMessage("", "CA1001")]
|
[SuppressMessage("", "CA1001")]
|
||||||
internal sealed partial class Activation : IActivation
|
internal sealed partial class Activation : IActivation
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 操作
|
|
||||||
/// </summary>
|
|
||||||
public const string Action = nameof(Action);
|
public const string Action = nameof(Action);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Uid
|
|
||||||
/// </summary>
|
|
||||||
public const string Uid = nameof(Uid);
|
public const string Uid = nameof(Uid);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 启动游戏启动参数
|
|
||||||
/// </summary>
|
|
||||||
public const string LaunchGame = nameof(LaunchGame);
|
public const string LaunchGame = nameof(LaunchGame);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从剪贴板导入成就
|
|
||||||
/// </summary>
|
|
||||||
public const string ImportUIAFFromClipboard = nameof(ImportUIAFFromClipboard);
|
public const string ImportUIAFFromClipboard = nameof(ImportUIAFFromClipboard);
|
||||||
|
|
||||||
private const string CategoryAchievement = "ACHIEVEMENT";
|
private const string CategoryAchievement = "ACHIEVEMENT";
|
||||||
@@ -52,50 +37,50 @@ internal sealed partial class Activation : IActivation
|
|||||||
private readonly ICurrentWindowReference currentWindowReference;
|
private readonly ICurrentWindowReference currentWindowReference;
|
||||||
private readonly ITaskContext taskContext;
|
private readonly ITaskContext taskContext;
|
||||||
private readonly SemaphoreSlim activateSemaphore = new(1);
|
private readonly SemaphoreSlim activateSemaphore = new(1);
|
||||||
|
private readonly AppNotificationManager appNotificationManager = AppNotificationManager.Default;
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Activate(object? sender, AppActivationArguments args)
|
|
||||||
{
|
|
||||||
_ = sender;
|
|
||||||
if (!ToastNotificationManagerCompat.WasCurrentProcessToastActivated())
|
|
||||||
{
|
|
||||||
HandleActivationAsync(args, true).SafeForget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void NonRedirectToActivate(object? sender, AppActivationArguments args)
|
public void NonRedirectToActivate(object? sender, AppActivationArguments args)
|
||||||
{
|
{
|
||||||
_ = sender;
|
HandleActivationAsync(args, false).SafeForget();
|
||||||
if (!ToastNotificationManagerCompat.WasCurrentProcessToastActivated())
|
|
||||||
{
|
|
||||||
HandleActivationAsync(args, false).SafeForget();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void InitializeWith(AppInstance appInstance)
|
public void InitializeWith(AppInstance appInstance)
|
||||||
{
|
{
|
||||||
appInstance.Activated += Activate;
|
appInstance.Activated += OnAppInstanceActivate;
|
||||||
ToastNotificationManagerCompat.OnActivated += NotificationActivate;
|
appNotificationManager.NotificationInvoked += OnAppNotificationManagerNotificationInvoked;
|
||||||
|
appNotificationManager.Register();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NotificationActivate(ToastNotificationActivatedEventArgsCompat args)
|
private void OnAppInstanceActivate(object? sender, AppActivationArguments args)
|
||||||
{
|
{
|
||||||
ToastArguments toastArgs = ToastArguments.Parse(args.Argument);
|
HandleActivationAsync(args, true).SafeForget();
|
||||||
|
}
|
||||||
|
|
||||||
if (toastArgs.TryGetValue(Action, out string? action))
|
private void OnAppNotificationManagerNotificationInvoked(AppNotificationManager manager, AppNotificationActivatedEventArgs args)
|
||||||
|
{
|
||||||
|
IDictionary<string, string> arguments = args.Arguments;
|
||||||
|
HandleAppNotificationActivationAsync(arguments).SafeForget();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ValueTask HandleAppNotificationActivationAsync(IDictionary<string, string> arguments)
|
||||||
|
{
|
||||||
|
if (arguments.TryGetValue(Action, out string? action))
|
||||||
{
|
{
|
||||||
if (action == LaunchGame)
|
if (action == LaunchGame)
|
||||||
{
|
{
|
||||||
_ = toastArgs.TryGetValue(Uid, out string? uid);
|
if (arguments.TryGetValue(Uid, out string? uid))
|
||||||
HandleLaunchGameActionAsync(uid).SafeForget();
|
{
|
||||||
|
await HandleLaunchGameActionAsync(uid).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async ValueTask HandleActivationAsync(AppActivationArguments args, bool isRedirected)
|
private async ValueTask HandleActivationAsync(AppActivationArguments args, bool isRedirected)
|
||||||
{
|
{
|
||||||
|
// Refuse other activations
|
||||||
if (activateSemaphore.CurrentCount > 0)
|
if (activateSemaphore.CurrentCount > 0)
|
||||||
{
|
{
|
||||||
using (await activateSemaphore.EnterAsync().ConfigureAwait(false))
|
using (await activateSemaphore.EnterAsync().ConfigureAwait(false))
|
||||||
@@ -107,32 +92,42 @@ internal sealed partial class Activation : IActivation
|
|||||||
|
|
||||||
private async ValueTask HandleActivationCoreAsync(AppActivationArguments args, bool isRedirected)
|
private async ValueTask HandleActivationCoreAsync(AppActivationArguments args, bool isRedirected)
|
||||||
{
|
{
|
||||||
if (args.Kind == ExtendedActivationKind.Protocol)
|
switch (args.Kind)
|
||||||
{
|
{
|
||||||
if (args.TryGetProtocolActivatedUri(out Uri? uri))
|
case ExtendedActivationKind.Launch:
|
||||||
{
|
if (args.TryGetLaunchActivatedArgument(out string? command))
|
||||||
await HandleUrlActivationAsync(uri, isRedirected).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (args.Kind == ExtendedActivationKind.Launch)
|
|
||||||
{
|
|
||||||
if (args.TryGetLaunchActivatedArgument(out string? arguments))
|
|
||||||
{
|
|
||||||
switch (arguments)
|
|
||||||
{
|
{
|
||||||
case LaunchGame:
|
switch (command)
|
||||||
{
|
{
|
||||||
await HandleLaunchGameActionAsync().ConfigureAwait(false);
|
case LaunchGame:
|
||||||
break;
|
{
|
||||||
}
|
await HandleLaunchGameActionAsync().ConfigureAwait(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
await HandleNormalLaunchActionAsync().ConfigureAwait(false);
|
await HandleNormalLaunchActionAsync().ConfigureAwait(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
break;
|
||||||
|
case ExtendedActivationKind.AppNotification:
|
||||||
|
if (args.TryGetAppNotificationActivatedArgument(out IDictionary<string, string>? arguments))
|
||||||
|
{
|
||||||
|
await HandleAppNotificationActivationAsync(arguments).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ExtendedActivationKind.Protocol:
|
||||||
|
if (args.TryGetProtocolActivatedUri(out Uri? uri))
|
||||||
|
{
|
||||||
|
await HandleUrlActivationAsync(uri, isRedirected).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,8 +207,6 @@ internal sealed partial class Activation : IActivation
|
|||||||
|
|
||||||
private async ValueTask HandleAchievementActionAsync(string action, string parameter, bool isRedirected)
|
private async ValueTask HandleAchievementActionAsync(string action, string parameter, bool isRedirected)
|
||||||
{
|
{
|
||||||
_ = parameter;
|
|
||||||
_ = isRedirected;
|
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case UrlActionImport:
|
case UrlActionImport:
|
||||||
@@ -232,7 +225,6 @@ internal sealed partial class Activation : IActivation
|
|||||||
|
|
||||||
private async ValueTask HandleDailyNoteActionAsync(string action, string parameter, bool isRedirected)
|
private async ValueTask HandleDailyNoteActionAsync(string action, string parameter, bool isRedirected)
|
||||||
{
|
{
|
||||||
_ = parameter;
|
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case UrlActionRefresh:
|
case UrlActionRefresh:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using Microsoft.Windows.AppLifecycle;
|
using Microsoft.Windows.AppLifecycle;
|
||||||
|
using Microsoft.Windows.AppNotifications;
|
||||||
using Windows.ApplicationModel.Activation;
|
using Windows.ApplicationModel.Activation;
|
||||||
|
|
||||||
namespace Snap.Hutao.Core.LifeCycle;
|
namespace Snap.Hutao.Core.LifeCycle;
|
||||||
@@ -47,4 +48,16 @@ internal static class AppActivationArgumentsExtensions
|
|||||||
arguments = launchArgs.Arguments.Trim();
|
arguments = launchArgs.Arguments.Trim();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool TryGetAppNotificationActivatedArgument(this AppActivationArguments activatedEventArgs, [NotNullWhen(true)] out IDictionary<string, string>? arguments)
|
||||||
|
{
|
||||||
|
arguments = null;
|
||||||
|
if (activatedEventArgs.Data is not AppNotificationActivatedEventArgs launchArgs)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments = launchArgs.Arguments;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,14 +10,6 @@ namespace Snap.Hutao.Core.LifeCycle;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal interface IActivation
|
internal interface IActivation
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 响应激活事件
|
|
||||||
/// 激活事件一般不会在UI线程上触发
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">发送方</param>
|
|
||||||
/// <param name="args">激活参数</param>
|
|
||||||
void Activate(object? sender, AppActivationArguments args);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 使用当前 App 实例初始化激活
|
/// 使用当前 App 实例初始化激活
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
</desktop:Extension>
|
</desktop:Extension>
|
||||||
<com:Extension Category="windows.comServer">
|
<com:Extension Category="windows.comServer">
|
||||||
<com:ComServer>
|
<com:ComServer>
|
||||||
<com:ExeServer Executable="Snap.Hutao.exe" Arguments="-ToastActivated" DisplayName="Snap Hutao Toast Activator">
|
<com:ExeServer Executable="Snap.Hutao.exe" Arguments="----AppNotificationActivated:" DisplayName="Snap Hutao Toast Activator">
|
||||||
<com:Class Id="5760ec4d-f7e8-4666-a965-9886d7dffe7d" DisplayName="Snap Hutao Toast Activator"/>
|
<com:Class Id="5760ec4d-f7e8-4666-a965-9886d7dffe7d" DisplayName="Snap Hutao Toast Activator"/>
|
||||||
</com:ExeServer>
|
</com:ExeServer>
|
||||||
</com:ComServer>
|
</com:ComServer>
|
||||||
|
|||||||
@@ -1,7 +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 CommunityToolkit.WinUI.Notifications;
|
using Microsoft.Windows.AppNotifications;
|
||||||
|
using Microsoft.Windows.AppNotifications.Builder;
|
||||||
using Snap.Hutao.Core;
|
using Snap.Hutao.Core;
|
||||||
using Snap.Hutao.Core.LifeCycle;
|
using Snap.Hutao.Core.LifeCycle;
|
||||||
using Snap.Hutao.Model.Entity;
|
using Snap.Hutao.Model.Entity;
|
||||||
@@ -63,18 +64,16 @@ internal sealed partial class DailyNoteNotificationOperation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ToastContentBuilder builder = new ToastContentBuilder()
|
AppNotificationBuilder builder = new AppNotificationBuilder()
|
||||||
.AddHeader(ToastHeaderIdArgument, SH.ServiceDailyNoteNotifierTitle, ToastHeaderIdArgument)
|
.AddText(SH.ServiceDailyNoteNotifierTitle, new AppNotificationTextProperties().SetMaxLines(1))
|
||||||
.AddAttributionText(attribution)
|
.SetAttributionText(attribution)
|
||||||
.AddButton(new ToastButton()
|
.AddButton(new AppNotificationButton(SH.ServiceDailyNoteNotifierActionLaunchGameButton)
|
||||||
.SetContent(SH.ServiceDailyNoteNotifierActionLaunchGameButton)
|
|
||||||
.AddArgument(Activation.Action, Activation.LaunchGame)
|
.AddArgument(Activation.Action, Activation.LaunchGame)
|
||||||
.AddArgument(Activation.Uid, entry.Uid))
|
.AddArgument(Activation.Uid, entry.Uid));
|
||||||
.AddButton(new ToastButtonDismiss(SH.ServiceDailyNoteNotifierActionLaunchGameDismiss));
|
|
||||||
|
|
||||||
if (options.IsReminderNotification)
|
if (options.IsReminderNotification)
|
||||||
{
|
{
|
||||||
builder.SetToastScenario(ToastScenario.Reminder);
|
builder.SetScenario(AppNotificationScenario.Reminder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notifyInfos.Count > 2)
|
if (notifyInfos.Count > 2)
|
||||||
@@ -101,7 +100,7 @@ internal sealed partial class DailyNoteNotificationOperation
|
|||||||
group.Children.Add(subgroup);
|
group.Children.Add(subgroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.AddVisualChild(group);
|
builder.SetGroup(group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -121,14 +120,14 @@ internal sealed partial class DailyNoteNotificationOperation
|
|||||||
// Image limitation.
|
// Image limitation.
|
||||||
// https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/send-local-toast?tabs=uwp#adding-images
|
// https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/send-local-toast?tabs=uwp#adding-images
|
||||||
// NotifySuppressed judge
|
// NotifySuppressed judge
|
||||||
ChcekResinNotifySuppressed(entry, notifyInfos);
|
CheckResinNotifySuppressed(entry, notifyInfos);
|
||||||
CheckHomeCoinNotifySuppressed(entry, notifyInfos);
|
CheckHomeCoinNotifySuppressed(entry, notifyInfos);
|
||||||
CheckDailyTaskNotifySuppressed(entry, notifyInfos);
|
CheckDailyTaskNotifySuppressed(entry, notifyInfos);
|
||||||
CheckTransformerNotifySuppressed(entry, notifyInfos);
|
CheckTransformerNotifySuppressed(entry, notifyInfos);
|
||||||
CheckExpeditionNotifySuppressed(entry, notifyInfos);
|
CheckExpeditionNotifySuppressed(entry, notifyInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ChcekResinNotifySuppressed(DailyNoteEntry entry, List<DailyNoteNotifyInfo> notifyInfos)
|
private static void CheckResinNotifySuppressed(DailyNoteEntry entry, List<DailyNoteNotifyInfo> notifyInfos)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(entry.DailyNote);
|
ArgumentNullException.ThrowIfNull(entry.DailyNote);
|
||||||
if (entry.DailyNote.CurrentResin >= entry.ResinNotifyThreshold)
|
if (entry.DailyNote.CurrentResin >= entry.ResinNotifyThreshold)
|
||||||
|
|||||||
@@ -267,9 +267,8 @@
|
|||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.0.230907" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.230907" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.230907" />
|
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.12" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.13" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.12">
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.13">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
Reference in New Issue
Block a user