Rework launch action propagatioon on Windows
This commit is contained in:
@@ -15,8 +15,10 @@ namespace DesktopNotifications.Apple
|
||||
{
|
||||
}
|
||||
|
||||
public event EventHandler<NotificationActivatedEventArgs> NotificationActivated;
|
||||
public event EventHandler<NotificationDismissedEventArgs> NotificationDismissed;
|
||||
public event EventHandler<NotificationActivatedEventArgs>? NotificationActivated;
|
||||
public event EventHandler<NotificationDismissedEventArgs>? NotificationDismissed;
|
||||
|
||||
public string? LaunchActionId { get; }
|
||||
|
||||
public ValueTask Initialize()
|
||||
{
|
||||
|
||||
@@ -21,35 +21,34 @@ namespace DesktopNotifications.Avalonia
|
||||
public static TAppBuilder SetupDesktopNotifications<TAppBuilder>(this TAppBuilder builder)
|
||||
where TAppBuilder : AppBuilderBase<TAppBuilder>, new()
|
||||
{
|
||||
return builder.AfterSetup(async b =>
|
||||
INotificationManager manager;
|
||||
var runtimeInfo = builder.RuntimePlatform.GetRuntimeInfo();
|
||||
|
||||
switch (runtimeInfo.OperatingSystem)
|
||||
{
|
||||
var runtimeInfo = b.RuntimePlatform.GetRuntimeInfo();
|
||||
INotificationManager manager;
|
||||
|
||||
switch (runtimeInfo.OperatingSystem)
|
||||
case OperatingSystemType.WinNT:
|
||||
{
|
||||
case OperatingSystemType.WinNT:
|
||||
{
|
||||
var context = WindowsApplicationContext.FromCurrentProcess(b.Instance.Name);
|
||||
manager = new WindowsNotificationManager(context);
|
||||
break;
|
||||
}
|
||||
|
||||
case OperatingSystemType.Linux:
|
||||
{
|
||||
var context = FreeDesktopApplicationContext.FromCurrentProcess();
|
||||
manager = new FreeDesktopNotificationManager(context);
|
||||
break;
|
||||
}
|
||||
|
||||
//TODO: OSX once implemented/stable
|
||||
default: return;
|
||||
var context = WindowsApplicationContext.FromCurrentProcess();
|
||||
manager = new WindowsNotificationManager(context);
|
||||
break;
|
||||
}
|
||||
|
||||
await manager.Initialize();
|
||||
case OperatingSystemType.Linux:
|
||||
{
|
||||
var context = FreeDesktopApplicationContext.FromCurrentProcess();
|
||||
manager = new FreeDesktopNotificationManager(context);
|
||||
break;
|
||||
}
|
||||
|
||||
AvaloniaLocator.CurrentMutable.Bind<INotificationManager>().ToConstant(manager);
|
||||
});
|
||||
//TODO: OSX once implemented/stable
|
||||
default: return builder;
|
||||
}
|
||||
|
||||
//manager.Initialize();
|
||||
|
||||
AvaloniaLocator.CurrentMutable.Bind<INotificationManager>().ToConstant(manager);
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,8 @@ namespace DesktopNotifications.FreeDesktop
|
||||
public event EventHandler<NotificationActivatedEventArgs>? NotificationActivated;
|
||||
public event EventHandler<NotificationDismissedEventArgs>? NotificationDismissed;
|
||||
|
||||
public string? LaunchActionId { get; }
|
||||
|
||||
public async ValueTask Initialize()
|
||||
{
|
||||
_connection = Connection.Session;
|
||||
|
||||
@@ -18,15 +18,16 @@ namespace DesktopNotifications.Windows
|
||||
private static extern void SetCurrentProcessExplicitAppUserModelID(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string appId);
|
||||
|
||||
public static WindowsApplicationContext FromCurrentProcess(string? customName = null,
|
||||
public static WindowsApplicationContext FromCurrentProcess(
|
||||
string? customName = null,
|
||||
string? appUserModelId = null)
|
||||
{
|
||||
var aumid = appUserModelId ?? Guid.NewGuid().ToString();
|
||||
var mainModule = Process.GetCurrentProcess().MainModule;
|
||||
var appName = customName ?? Path.GetFileNameWithoutExtension(mainModule.FileName);
|
||||
var aumid = appUserModelId ?? appName; //TODO: Add seeded bits to avoid collisions?
|
||||
|
||||
SetCurrentProcessExplicitAppUserModelID(aumid);
|
||||
|
||||
var mainModule = Process.GetCurrentProcess().MainModule;
|
||||
|
||||
using var shortcut = new ShellLink
|
||||
{
|
||||
TargetPath = mainModule.FileName,
|
||||
@@ -36,7 +37,6 @@ namespace DesktopNotifications.Windows
|
||||
|
||||
var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
var startMenuPath = Path.Combine(appData, @"Microsoft\Windows\Start Menu\Programs");
|
||||
var appName = customName ?? Path.GetFileNameWithoutExtension(mainModule.FileName);
|
||||
var shortcutFile = Path.Combine(startMenuPath, $"{appName}.lnk");
|
||||
|
||||
shortcut.Save(shortcutFile);
|
||||
|
||||
@@ -10,12 +10,11 @@ namespace DesktopNotifications.Windows
|
||||
{
|
||||
public class WindowsNotificationManager : INotificationManager
|
||||
{
|
||||
private const int LaunchNotificationWaitMs = 5_000;
|
||||
private readonly WindowsApplicationContext _applicationContext;
|
||||
private readonly TaskCompletionSource<string>? _launchActionPromise;
|
||||
private readonly Dictionary<ToastNotification, Notification> _notifications;
|
||||
private readonly ToastNotifier _toastNotifier;
|
||||
private string? _launchAction;
|
||||
private TaskCompletionSource<string?>? _launchActionPromise;
|
||||
private EventHandler<NotificationActivatedEventArgs>? _notificationActivatedHandler;
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
@@ -23,35 +22,31 @@ namespace DesktopNotifications.Windows
|
||||
public WindowsNotificationManager(WindowsApplicationContext? applicationContext = null)
|
||||
{
|
||||
_applicationContext = applicationContext ?? WindowsApplicationContext.FromCurrentProcess();
|
||||
_toastNotifier = ToastNotificationManager.CreateToastNotifier(_applicationContext.AppUserModelId);
|
||||
_launchActionPromise = new TaskCompletionSource<string>();
|
||||
|
||||
if (ToastNotificationManagerCompat.WasCurrentProcessToastActivated())
|
||||
{
|
||||
ToastNotificationManagerCompat.OnActivated += OnAppActivated;
|
||||
|
||||
if (_launchActionPromise.Task.Wait(LaunchNotificationWaitMs))
|
||||
{
|
||||
LaunchActionId = _launchActionPromise.Task.Result;
|
||||
}
|
||||
}
|
||||
|
||||
_toastNotifier = ToastNotificationManagerCompat.CreateToastNotifier();
|
||||
_notifications = new Dictionary<ToastNotification, Notification>();
|
||||
}
|
||||
|
||||
public event EventHandler<NotificationActivatedEventArgs>? NotificationActivated
|
||||
{
|
||||
add
|
||||
{
|
||||
_notificationActivatedHandler += value;
|
||||
ProcessLaunchAction();
|
||||
}
|
||||
remove => _notificationActivatedHandler -= value;
|
||||
}
|
||||
public event EventHandler<NotificationActivatedEventArgs>? NotificationActivated;
|
||||
|
||||
public event EventHandler<NotificationDismissedEventArgs>? NotificationDismissed;
|
||||
|
||||
public async ValueTask Initialize()
|
||||
public string? LaunchActionId { get; }
|
||||
|
||||
public ValueTask Initialize()
|
||||
{
|
||||
if (ToastNotificationManagerCompat.WasCurrentProcessToastActivated())
|
||||
{
|
||||
_launchActionPromise = new TaskCompletionSource<string?>();
|
||||
ToastNotificationManagerCompat.OnActivated += OnAppActivated;
|
||||
|
||||
_launchAction = await _launchActionPromise.Task;
|
||||
|
||||
Debug.Assert(_launchAction != null);
|
||||
|
||||
ProcessLaunchAction();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
|
||||
public ValueTask ShowNotification(Notification notification, DateTimeOffset? expirationTime)
|
||||
@@ -79,20 +74,7 @@ namespace DesktopNotifications.Windows
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
private void ProcessLaunchAction()
|
||||
{
|
||||
if (_launchAction == null || _notificationActivatedHandler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: Lookup notification object from history?
|
||||
_notificationActivatedHandler.Invoke(this,
|
||||
new NotificationActivatedEventArgs(null!, _launchAction));
|
||||
|
||||
_launchAction = null;
|
||||
ToastNotificationManagerCompat.Uninstall();
|
||||
}
|
||||
|
||||
private static XmlDocument GenerateXml(Notification notification)
|
||||
@@ -113,7 +95,9 @@ namespace DesktopNotifications.Windows
|
||||
private void OnAppActivated(ToastNotificationActivatedEventArgsCompat e)
|
||||
{
|
||||
Debug.Assert(_launchActionPromise != null);
|
||||
_launchActionPromise.SetResult(e.Argument);
|
||||
|
||||
var actionId = GetActionId(e.Argument);
|
||||
_launchActionPromise.SetResult(actionId);
|
||||
}
|
||||
|
||||
private static void ToastNotificationOnFailed(ToastNotification sender, ToastFailedEventArgs args)
|
||||
@@ -137,13 +121,18 @@ namespace DesktopNotifications.Windows
|
||||
_notifications.Remove(sender);
|
||||
}
|
||||
|
||||
private static string GetActionId(string argument)
|
||||
{
|
||||
return string.IsNullOrEmpty(argument) ? "default" : argument;
|
||||
}
|
||||
|
||||
private void ToastNotificationOnActivated(ToastNotification sender, object args)
|
||||
{
|
||||
var activationArgs = (ToastActivatedEventArgs) args;
|
||||
var notification = _notifications[sender];
|
||||
var actionId = string.IsNullOrEmpty(activationArgs.Arguments) ? "default" : activationArgs.Arguments;
|
||||
var actionId = GetActionId(activationArgs.Arguments);
|
||||
|
||||
_notificationActivatedHandler?.Invoke(this, new NotificationActivatedEventArgs(notification, actionId));
|
||||
NotificationActivated?.Invoke(this, new NotificationActivatedEventArgs(notification, actionId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace DesktopNotifications
|
||||
namespace DesktopNotifications
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ApplicationContext
|
||||
{
|
||||
@@ -15,9 +10,7 @@ namespace DesktopNotifications
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,18 +8,22 @@ namespace DesktopNotifications
|
||||
/// </summary>
|
||||
public interface INotificationManager : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
string? LaunchActionId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a notification was activated. The notion of "activation" varies from platform to platform.
|
||||
/// </summary>
|
||||
event EventHandler<NotificationActivatedEventArgs> NotificationActivated;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a notification was dismissed. The exact reason can be found in <see cref="NotificationDismissedEventArgs"/>.
|
||||
/// Raised when a notification was dismissed. The exact reason can be found in
|
||||
/// <see cref="NotificationDismissedEventArgs" />.
|
||||
/// </summary>
|
||||
event EventHandler<NotificationDismissedEventArgs> NotificationDismissed;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
ValueTask Initialize();
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Notification Notification { get; }
|
||||
}
|
||||
|
||||
@@ -31,6 +31,11 @@ namespace Example.Avalonia
|
||||
_notificationManager = AvaloniaLocator.Current.GetService<INotificationManager>();
|
||||
_notificationManager.NotificationActivated += OnNotificationActivated;
|
||||
_notificationManager.NotificationDismissed += OnNotificationDismissed;
|
||||
|
||||
if (_notificationManager.LaunchActionId != null)
|
||||
{
|
||||
((IList<string>) _eventsListBox.Items).Add($"Launch action: {_notificationManager.LaunchActionId}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNotificationDismissed(object? sender, NotificationDismissedEventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user