Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shell NotifyIcon Support #1620

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/alpha.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- main
- develop
- 'feat/*'
paths-ignore:
- '.gitattributes'
- '.github/**'
Expand Down
1 change: 1 addition & 0 deletions src/Snap.Hutao/Snap.Hutao/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources/>
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.SettingsControls/SettingsCard/SettingsCard.xaml"/>
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.TokenizingTextBox/TokenizingTextBox.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Loading.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Image/CachedImage.xaml"/>
Expand Down
24 changes: 15 additions & 9 deletions src/Snap.Hutao/Snap.Hutao/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
using Snap.Hutao.Core.LifeCycle;
using Snap.Hutao.Core.LifeCycle.InterProcess;
using Snap.Hutao.Core.Logging;
using Snap.Hutao.Core.Shell;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Core.Windowing.HotKey;
using Snap.Hutao.Core.Windowing.NotifyIcon;
using System.Diagnostics;

namespace Snap.Hutao;
Expand Down Expand Up @@ -39,7 +41,7 @@ Snap.Hutao is a open source software developed by DGP Studio.
""";

private readonly IServiceProvider serviceProvider;
private readonly IActivation activation;
private readonly IAppActivation activation;
private readonly ILogger<App> logger;

/// <summary>
Expand All @@ -48,17 +50,23 @@ Snap.Hutao is a open source software developed by DGP Studio.
/// <param name="serviceProvider">服务提供器</param>
public App(IServiceProvider serviceProvider)
{
// DispatcherShutdownMode = DispatcherShutdownMode.OnExplicitShutdown;

// Load app resource
InitializeComponent();
activation = serviceProvider.GetRequiredService<IActivation>();
activation = serviceProvider.GetRequiredService<IAppActivation>();
logger = serviceProvider.GetRequiredService<ILogger<App>>();
serviceProvider.GetRequiredService<ExceptionRecorder>().Record(this);

this.serviceProvider = serviceProvider;
}

public bool IsExiting { get; private set; }

public new void Exit()
{
IsExiting = true;
base.Exit();
}

/// <inheritdoc/>
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
Expand All @@ -75,11 +83,9 @@ protected override void OnLaunched(LaunchActivatedEventArgs args)
logger.LogColorizedInformation((ConsoleBanner, ConsoleColor.DarkYellow));
LogDiagnosticInformation();

// manually invoke
// Manually invoke
activation.Activate(HutaoActivationArguments.FromAppActivationArguments(activatedEventArgs));
activation.Initialize();

serviceProvider.GetRequiredService<IJumpListInterop>().ConfigureAsync().SafeForget();
activation.PostInitialization();
}
catch
{
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

using CommunityToolkit.WinUI.Notifications;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.UI.Xaml;
using Snap.Hutao.Core.LifeCycle.InterProcess;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Core.Windowing.HotKey;
using Snap.Hutao.Core.Windowing.NotifyIcon;
using Snap.Hutao.Service.DailyNote;
using Snap.Hutao.Service.Discord;
using Snap.Hutao.Service.Hutao;
Expand All @@ -20,9 +23,9 @@ namespace Snap.Hutao.Core.LifeCycle;
/// </summary>
[HighQuality]
[ConstructorGenerated]
[Injection(InjectAs.Singleton, typeof(IActivation))]
[Injection(InjectAs.Singleton, typeof(IAppActivation))]
[SuppressMessage("", "CA1001")]
internal sealed partial class Activation : IActivation
internal sealed partial class AppActivation : IAppActivation, IAppActivationActionHandlersAccess, IDisposable
{
public const string Action = nameof(Action);
public const string Uid = nameof(Uid);
Expand All @@ -35,13 +38,15 @@ internal sealed partial class Activation : IActivation
private const string UrlActionRefresh = "/REFRESH";

private readonly IServiceProvider serviceProvider;
private readonly ICurrentWindowReference currentWindowReference;
private readonly ICurrentXamlWindowReference currentWindowReference;
private readonly ITaskContext taskContext;
private readonly SemaphoreSlim activateSemaphore = new(1);

/// <inheritdoc/>
public void Activate(HutaoActivationArguments args)
{
// Before activate, we try to redirect to the opened process in App,
// And we check if it's a toast activation.
if (ToastNotificationManagerCompat.WasCurrentProcessToastActivated())
{
return;
Expand All @@ -51,10 +56,52 @@ public void Activate(HutaoActivationArguments args)
}

/// <inheritdoc/>
public void Initialize()
public void PostInitialization()
{
serviceProvider.GetRequiredService<PrivateNamedPipeServer>().RunAsync().SafeForget();
ToastNotificationManagerCompat.OnActivated += NotificationActivate;

serviceProvider.GetRequiredService<HotKeyOptions>().RegisterAll();
if (LocalSetting.Get(SettingKeys.IsNotifyIconEnabled, true))
{
serviceProvider.GetRequiredService<App>().DispatcherShutdownMode = DispatcherShutdownMode.OnExplicitShutdown;
_ = serviceProvider.GetRequiredService<NotifyIconController>();
}
}

public void Dispose()
{
activateSemaphore.Dispose();
}

public async ValueTask HandleLaunchGameActionAsync(string? uid = null)
{
serviceProvider
.GetRequiredService<IMemoryCache>()
.Set(ViewModel.Game.LaunchGameViewModel.DesiredUid, uid);

await taskContext.SwitchToMainThreadAsync();

if (currentWindowReference.Window is null)
{
currentWindowReference.Window = serviceProvider.GetRequiredService<LaunchGameWindow>();
return;
}

if (currentWindowReference.Window is MainWindow)
{
await serviceProvider
.GetRequiredService<INavigationService>()
.NavigateAsync<View.Page.LaunchGamePage>(INavigationAwaiter.Default, true)
.ConfigureAwait(false);

return;
}
else
{
// We have a non-Main Window, just exit current process anyway
Process.GetCurrentProcess().Kill();
}
}

private void NotificationActivate(ToastNotificationActivatedEventArgsCompat args)
Expand Down Expand Up @@ -94,12 +141,6 @@ private async ValueTask HandleActivationCoreAsync(HutaoActivationArguments args)
ArgumentNullException.ThrowIfNull(args.LaunchActivatedArguments);
switch (args.LaunchActivatedArguments)
{
case LaunchGame:
{
await HandleLaunchGameActionAsync().ConfigureAwait(false);
break;
}

default:
{
await HandleNormalLaunchActionAsync().ConfigureAwait(false);
Expand All @@ -112,10 +153,9 @@ private async ValueTask HandleActivationCoreAsync(HutaoActivationArguments args)
private async ValueTask HandleNormalLaunchActionAsync()
{
// Increase launch times
LocalSetting.Update(SettingKeys.LaunchTimes, 0, x => x + 1);
LocalSetting.Update(SettingKeys.LaunchTimes, 0, x => unchecked(x + 1));

// If it's the first time launch, we show the guide window anyway.
// Otherwise, we check if there's any unfulfilled resource category present.
// If the guide is completed, we check if there's any unfulfilled resource category present.
if (UnsafeLocalSetting.Get(SettingKeys.Major1Minor10Revision0GuideState, GuideState.Language) >= GuideState.StaticResourceBegin)
{
if (StaticResource.IsAnyUnfulfilledCategoryPresent())
Expand All @@ -124,10 +164,11 @@ private async ValueTask HandleNormalLaunchActionAsync()
}
}

// If it's the first time launch, show the guide window anyway.
if (UnsafeLocalSetting.Get(SettingKeys.Major1Minor10Revision0GuideState, GuideState.Language) < GuideState.Completed)
{
await taskContext.SwitchToMainThreadAsync();
serviceProvider.GetRequiredService<GuideWindow>();
currentWindowReference.Window = serviceProvider.GetRequiredService<GuideWindow>();
}
else
{
Expand All @@ -144,7 +185,7 @@ private async ValueTask WaitMainWindowAsync()

await taskContext.SwitchToMainThreadAsync();

serviceProvider.GetRequiredService<MainWindow>();
currentWindowReference.Window = serviceProvider.GetRequiredService<MainWindow>();

await taskContext.SwitchToBackgroundAsync();

Expand All @@ -158,10 +199,7 @@ private async ValueTask WaitMainWindowAsync()
hutaoUserServiceInitialization.InitializeInternalAsync().SafeForget();
}

serviceProvider
.GetRequiredService<IDiscordService>()
.SetNormalActivityAsync()
.SafeForget();
serviceProvider.GetRequiredService<IDiscordService>().SetNormalActivityAsync().SafeForget();
}

private async ValueTask HandleUrlActivationAsync(Uri uri, bool isRedirectTo)
Expand Down Expand Up @@ -244,34 +282,4 @@ await serviceProvider
}
}
}

private async ValueTask HandleLaunchGameActionAsync(string? uid = null)
{
serviceProvider
.GetRequiredService<IMemoryCache>()
.Set(ViewModel.Game.LaunchGameViewModel.DesiredUid, uid);

await taskContext.SwitchToMainThreadAsync();

if (currentWindowReference.Window is null)
{
serviceProvider.GetRequiredService<LaunchGameWindow>();
return;
}

if (currentWindowReference.Window is MainWindow)
{
await serviceProvider
.GetRequiredService<INavigationService>()
.NavigateAsync<View.Page.LaunchGamePage>(INavigationAwaiter.Default, true)
.ConfigureAwait(false);

return;
}
else
{
// We have a non-Main Window, just exit current process anyway
Process.GetCurrentProcess().Kill();
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@

namespace Snap.Hutao.Core.LifeCycle;

[Injection(InjectAs.Singleton, typeof(ICurrentWindowReference))]
internal sealed class CurrentWindowReference : ICurrentWindowReference
[Injection(InjectAs.Singleton, typeof(ICurrentXamlWindowReference))]
internal sealed class CurrentXamlWindowReference : ICurrentXamlWindowReference
{
private readonly WeakReference<Window> reference = new(default!);

[SuppressMessage("", "SH007")]
public Window Window
public Window? Window
{
get
{
reference.TryGetTarget(out Window? window);
return window!;
}
set => reference.SetTarget(value);
set => reference.SetTarget(value!);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.

using Microsoft.UI.Xaml;
using Snap.Hutao.Core.Windowing;
using Snap.Hutao.Win32.Foundation;
using WinRT.Interop;

namespace Snap.Hutao.Core.LifeCycle;

internal static class CurrentXamlWindowReferenceExtension
{
public static XamlRoot GetXamlRoot(this ICurrentXamlWindowReference reference)
{
ArgumentNullException.ThrowIfNull(reference.Window);
return reference.Window.Content.XamlRoot;
}

public static HWND GetWindowHandle(this ICurrentXamlWindowReference reference)
{
return WindowExtension.GetWindowHandle(reference.Window);
}
}
14 changes: 0 additions & 14 deletions src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/IActivation.cs

This file was deleted.

Loading
Loading