Compare commits

..

49 Commits

Author SHA1 Message Date
Lightczx
957b63ac32 1.7.13 package 2023-10-30 19:33:59 +08:00
Masterain
3af8f356cc New translations sh.resx (English) 2023-10-30 19:33:58 +08:00
Masterain
05608cee30 New translations sh.resx (Chinese Traditional) 2023-10-30 19:33:58 +08:00
Masterain
f8d7f72679 New translations sh.resx (Korean) 2023-10-30 19:33:58 +08:00
Masterain
1564f2a97e New translations sh.resx (Japanese) 2023-10-30 19:33:58 +08:00
Masterain
1f5619baa0 New translations sh.resx (Japanese) 2023-10-30 19:33:58 +08:00
Lightczx
7406f5822f ui/ux 2023-10-30 19:33:58 +08:00
Lightczx
38cffe4dc3 remove hutao user changed message 2023-10-30 19:33:27 +08:00
DismissedLight
ba4a7c1447 fix #903 2023-10-30 19:33:27 +08:00
DismissedLight
a03edeef3f implement #911 2023-10-30 19:33:27 +08:00
DismissedLight
981d2d74ee built in resx generator 2023-10-30 19:33:27 +08:00
Lightczx
27aa404e52 roslyn generated resx 2023-10-30 19:33:08 +08:00
Lightczx
78a56ec912 fix #431 input crash 2023-10-30 19:32:38 +08:00
Masterain
8f25769527 New translations sh.resx (English) 2023-10-30 19:32:38 +08:00
Masterain
85e31d122d New translations sh.resx (Chinese Traditional) 2023-10-30 19:32:38 +08:00
Masterain
65191d91bd New translations sh.resx (Korean) 2023-10-30 19:32:38 +08:00
Masterain
c885a6f220 New translations sh.resx (Japanese) 2023-10-30 19:32:38 +08:00
Masterain
3d0ea2dd4e New translations sh.resx (English) 2023-10-30 19:32:38 +08:00
Masterain
9d2e5896e6 New translations sh.resx (English) 2023-10-30 19:32:38 +08:00
Masterain
d376d9b3f6 New translations sh.resx (Chinese Traditional) 2023-10-30 19:32:38 +08:00
Masterain
449ae4499b New translations sh.resx (Korean) 2023-10-30 19:32:38 +08:00
Masterain
2d59fcfb21 New translations sh.resx (Japanese) 2023-10-30 19:32:37 +08:00
Masterain
5600d1fe9e New translations sh.resx (English) 2023-10-30 19:32:37 +08:00
Masterain
02ee082bd0 New translations sh.resx (Japanese) 2023-10-30 19:32:37 +08:00
Masterain
f4a1914735 New translations sh.resx (English) 2023-10-30 19:32:37 +08:00
Masterain
df8f317020 New translations sh.resx (Chinese Traditional) 2023-10-30 19:32:37 +08:00
Masterain
d09e4c3035 New translations sh.resx (Korean) 2023-10-30 19:32:37 +08:00
Masterain
e0d43b0dfb New translations sh.resx (Japanese) 2023-10-30 19:32:37 +08:00
DismissedLight
805d8ed87d ignore designer file 2 2023-10-30 19:32:37 +08:00
DismissedLight
bbbe2eeb79 ignore designer file 1 2023-10-30 19:32:37 +08:00
DismissedLight
7b8cc1b4c3 impl #1021 2023-10-30 19:32:37 +08:00
Lightczx
7c357d3a1c typo fix 2023-10-30 19:32:37 +08:00
Lightczx
7fc4e1a0a3 implement #431 2023-10-30 19:32:37 +08:00
Lightczx
f29fa1e8a0 fix IsGameRunning 2023-10-30 19:32:37 +08:00
DismissedLight
9a54463d7d support server l10n 2023-10-30 19:32:37 +08:00
DismissedLight
ababf74473 fix #1041 2023-10-30 19:32:37 +08:00
Lightczx
ba7ba3af44 fix #899 2023-10-30 19:32:37 +08:00
Lightczx
91f6665849 fix #1023 2023-10-30 19:32:37 +08:00
Lightczx
154f6a1bb6 fix #1035 2023-10-30 19:32:37 +08:00
DismissedLight
45cca2185e launch page redo 2023-10-30 19:32:37 +08:00
DismissedLight
95631df4fa fix #925 2023-10-30 19:32:37 +08:00
Masterain
d8186082bf Update issue templates 2023-10-30 19:32:37 +08:00
Masterain
18d6ee214c Update .github configurations 2023-10-30 19:32:37 +08:00
DismissedLight
bfc967d244 1.7.11 hotfix package 2023-10-18 19:54:21 +08:00
DismissedLight
0c8f757d69 fix launch args 2023-10-18 19:54:21 +08:00
Lightczx
dda4e60813 fix #1028 2023-10-18 19:54:21 +08:00
Masterain
cc01269d9a Update FUNDING.yml 2023-10-18 19:54:20 +08:00
Masterain
b5706c316f Update FUNDING.yml 2023-10-18 19:54:20 +08:00
DismissedLight
bc0e2bd717 migrate to winappsdk notification 2023-10-17 22:13:46 +08:00
7 changed files with 83 additions and 88 deletions

View File

@@ -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();

View File

@@ -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:

View File

@@ -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;
}
} }

View File

@@ -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>

View File

@@ -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>

View File

@@ -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)

View File

@@ -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>