diff --git a/App/App.xaml.cs b/App/App.xaml.cs index 2c7e87e..2cdee97 100644 --- a/App/App.xaml.cs +++ b/App/App.xaml.cs @@ -21,6 +21,7 @@ using Microsoft.Windows.AppLifecycle; using Serilog; using LaunchActivatedEventArgs = Microsoft.UI.Xaml.LaunchActivatedEventArgs; +using Microsoft.Windows.AppNotifications; namespace Coder.Desktop.App; @@ -70,6 +71,7 @@ public App() services.AddOptions<MutagenControllerConfig>() .Bind(builder.Configuration.GetSection(MutagenControllerConfigSection)); services.AddSingleton<ISyncSessionController, MutagenController>(); + services.AddSingleton<IUserNotifier, UserNotifier>(); // SignInWindow views and view models services.AddTransient<SignInViewModel>(); @@ -188,10 +190,14 @@ public void OnActivated(object? sender, AppActivationArguments args) _logger.LogWarning("URI activation with null data"); return; } - HandleURIActivation(protoArgs.Uri); break; + case ExtendedActivationKind.AppNotification: + var notificationArgs = (args.Data as AppNotificationActivatedEventArgs)!; + HandleNotification(null, notificationArgs); + break; + default: _logger.LogWarning("activation for {kind}, which is unhandled", args.Kind); break; @@ -204,6 +210,12 @@ public void HandleURIActivation(Uri uri) _logger.LogInformation("handling URI activation for {path}", uri.AbsolutePath); } + public void HandleNotification(AppNotificationManager? sender, AppNotificationActivatedEventArgs args) + { + // right now, we don't do anything other than log + _logger.LogInformation("handled notification activation"); + } + private static void AddDefaultConfig(IConfigurationBuilder builder) { var logPath = Path.Combine( diff --git a/App/Program.cs b/App/Program.cs index 1a54b2b..3749c3b 100644 --- a/App/Program.cs +++ b/App/Program.cs @@ -5,6 +5,7 @@ using Microsoft.UI.Dispatching; using Microsoft.UI.Xaml; using Microsoft.Windows.AppLifecycle; +using Microsoft.Windows.AppNotifications; using WinRT; namespace Coder.Desktop.App; @@ -28,9 +29,9 @@ private static void Main(string[] args) { ComWrappersSupport.InitializeComWrappers(); var mainInstance = GetMainInstance(); + var activationArgs = AppInstance.GetCurrent().GetActivatedEventArgs(); if (!mainInstance.IsCurrent) { - var activationArgs = AppInstance.GetCurrent().GetActivatedEventArgs(); mainInstance.RedirectActivationToAsync(activationArgs).AsTask().Wait(); return; } @@ -58,6 +59,15 @@ private static void Main(string[] args) // redirections via RedirectActivationToAsync above get routed to the App mainInstance.Activated += app.OnActivated; + var notificationManager = AppNotificationManager.Default; + notificationManager.NotificationInvoked += app.HandleNotification; + notificationManager.Register(); + if (activationArgs.Kind != ExtendedActivationKind.Launch) + { + // this means we were activated without having already launched, so handle + // the activation as well. + app.OnActivated(null, activationArgs); + } }); } catch (Exception e) diff --git a/App/Services/UserNotifier.cs b/App/Services/UserNotifier.cs new file mode 100644 index 0000000..9cdf6c1 --- /dev/null +++ b/App/Services/UserNotifier.cs @@ -0,0 +1,29 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Windows.AppNotifications; +using Microsoft.Windows.AppNotifications.Builder; + +namespace Coder.Desktop.App.Services; + +public interface IUserNotifier : IAsyncDisposable +{ + public Task ShowErrorNotification(string title, string message); +} + +public class UserNotifier : IUserNotifier +{ + private readonly AppNotificationManager _notificationManager = AppNotificationManager.Default; + + public ValueTask DisposeAsync() + { + return ValueTask.CompletedTask; + } + + public Task ShowErrorNotification(string title, string message) + { + var builder = new AppNotificationBuilder().AddText(title).AddText(message); + _notificationManager.Show(builder.BuildNotification()); + return Task.CompletedTask; + } +} +