diff --git a/DesktopNotifications.Apple/AppleNotificationManager.cs b/DesktopNotifications.Apple/AppleNotificationManager.cs
index 76c2253..c2dbaeb 100644
--- a/DesktopNotifications.Apple/AppleNotificationManager.cs
+++ b/DesktopNotifications.Apple/AppleNotificationManager.cs
@@ -14,10 +14,12 @@ namespace DesktopNotifications.Apple
public ValueTask Initialize()
{
+ return default;
}
public ValueTask ShowNotification(Notification notification, DateTimeOffset? expirationTime = null)
{
+ return default;
}
}
}
diff --git a/DesktopNotifications.FreeDesktop/FreeDesktopApplicationContext.cs b/DesktopNotifications.FreeDesktop/FreeDesktopApplicationContext.cs
new file mode 100644
index 0000000..baa868c
--- /dev/null
+++ b/DesktopNotifications.FreeDesktop/FreeDesktopApplicationContext.cs
@@ -0,0 +1,28 @@
+using System.Diagnostics;
+using System.IO;
+
+namespace DesktopNotifications.FreeDesktop
+{
+ ///
+ ///
+ public class FreeDesktopApplicationContext : ApplicationContext
+ {
+ private FreeDesktopApplicationContext(string name, string? appIcon) : base(name)
+ {
+ AppIcon = appIcon;
+ }
+
+ ///
+ ///
+ public string? AppIcon { get; }
+
+ public static FreeDesktopApplicationContext FromCurrentProcess(string? appIcon = null)
+ {
+ var mainModule = Process.GetCurrentProcess().MainModule;
+ return new FreeDesktopApplicationContext(
+ Path.GetFileNameWithoutExtension(mainModule.FileName),
+ appIcon
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/DesktopNotifications.FreeDesktop/FreeDesktopNotificationManager.cs b/DesktopNotifications.FreeDesktop/FreeDesktopNotificationManager.cs
index 0792675..6f1b860 100644
--- a/DesktopNotifications.FreeDesktop/FreeDesktopNotificationManager.cs
+++ b/DesktopNotifications.FreeDesktop/FreeDesktopNotificationManager.cs
@@ -9,18 +9,24 @@ namespace DesktopNotifications.FreeDesktop
{
public class FreeDesktopNotificationManager : INotificationManager, IDisposable
{
+ private readonly FreeDesktopApplicationContext _appContext;
private const string NotificationsService = "org.freedesktop.Notifications";
private static readonly ObjectPath NotificationsPath = new ObjectPath("/org/freedesktop/Notifications");
+ private readonly Dictionary _activeNotifications;
private Connection? _connection;
private IDisposable? _notificationActionSubscription;
private IDisposable? _notificationCloseSubscription;
- private Dictionary _activeNotifications;
private IFreeDesktopNotificationsProxy? _proxy;
- public FreeDesktopNotificationManager()
+ ///
+ ///
+ ///
+ ///
+ public FreeDesktopNotificationManager(FreeDesktopApplicationContext? appContext = null)
{
+ _appContext = appContext ?? FreeDesktopApplicationContext.FromCurrentProcess();
_activeNotifications = new Dictionary();
}
@@ -65,11 +71,11 @@ namespace DesktopNotifications.FreeDesktop
var actions = GenerateActions(notification);
var id = await _proxy.NotifyAsync(
- "MyApp",
+ _appContext.Name,
0,
- string.Empty,
- notification.Title,
- notification.Body,
+ _appContext.AppIcon ?? string.Empty,
+ notification.Title ?? throw new ArgumentException(),
+ notification.Body ?? throw new ArgumentException(),
actions.ToArray(),
new Dictionary {{"urgency", 1}},
duration?.Milliseconds ?? 0
@@ -110,7 +116,7 @@ namespace DesktopNotifications.FreeDesktop
var dismissReason = GetReason(@event.reason);
- NotificationDismissed?.Invoke(this,
+ NotificationDismissed?.Invoke(this,
new NotificationDismissedEventArgs(notification, dismissReason));
}
@@ -123,7 +129,7 @@ namespace DesktopNotifications.FreeDesktop
{
var notification = _activeNotifications[@event.id];
- NotificationActivated?.Invoke(this,
+ NotificationActivated?.Invoke(this,
new NotificationActivatedEventArgs(notification, @event.actionKey));
}
}
diff --git a/Example/ShellLink.cs b/DesktopNotifications.Windows/ShellLink.cs
similarity index 99%
rename from Example/ShellLink.cs
rename to DesktopNotifications.Windows/ShellLink.cs
index 8ec1289..4cf6b7a 100644
--- a/Example/ShellLink.cs
+++ b/DesktopNotifications.Windows/ShellLink.cs
@@ -1,11 +1,10 @@
using System;
-using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
-namespace Example.Win32
+namespace DesktopNotifications.Windows
{
// Modified from http://smdn.jp/programming/tips/createlnk/
// Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
diff --git a/DesktopNotifications.Windows/WindowsApplicationContext.cs b/DesktopNotifications.Windows/WindowsApplicationContext.cs
new file mode 100644
index 0000000..01e37e6
--- /dev/null
+++ b/DesktopNotifications.Windows/WindowsApplicationContext.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace DesktopNotifications.Windows
+{
+ public class WindowsApplicationContext : ApplicationContext
+ {
+ private WindowsApplicationContext(string name, string appUserModelId) : base(name)
+ {
+ AppUserModelId = appUserModelId;
+ }
+
+ public string AppUserModelId { get; }
+
+ [DllImport("shell32.dll", SetLastError = true)]
+ private static extern void SetCurrentProcessExplicitAppUserModelID(
+ [MarshalAs(UnmanagedType.LPWStr)] string appId);
+
+ public static WindowsApplicationContext FromCurrentProcess(string? customName = null,
+ string? appUserModelId = null)
+ {
+ var aumid = appUserModelId ?? Guid.NewGuid().ToString();
+
+ SetCurrentProcessExplicitAppUserModelID(aumid);
+
+ var mainModule = Process.GetCurrentProcess().MainModule;
+
+ using var shortcut = new ShellLink
+ {
+ TargetPath = mainModule.FileName,
+ Arguments = string.Empty,
+ AppUserModelID = aumid
+ };
+
+ 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);
+
+ return new WindowsApplicationContext(appName, aumid);
+ }
+ }
+}
\ No newline at end of file
diff --git a/DesktopNotifications.Windows/WindowsNotificationManager.cs b/DesktopNotifications.Windows/WindowsNotificationManager.cs
index 8d7d377..1f23cf2 100644
--- a/DesktopNotifications.Windows/WindowsNotificationManager.cs
+++ b/DesktopNotifications.Windows/WindowsNotificationManager.cs
@@ -10,20 +10,33 @@ namespace DesktopNotifications.Windows
{
public class WindowsNotificationManager : INotificationManager
{
+ private readonly WindowsApplicationContext _applicationContext;
private readonly Dictionary _notifications;
private readonly ToastNotifier _toastNotifier;
+ private string? _launchAction;
private TaskCompletionSource? _launchActionPromise;
+ private EventHandler? _notificationActivatedHandler;
///
///
- ///
- public WindowsNotificationManager(string appId)
+ ///
+ public WindowsNotificationManager(WindowsApplicationContext? applicationContext = null)
{
- _toastNotifier = ToastNotificationManager.CreateToastNotifier(appId);
+ _applicationContext = applicationContext ?? WindowsApplicationContext.FromCurrentProcess();
+ _toastNotifier = ToastNotificationManager.CreateToastNotifier(_applicationContext.AppUserModelId);
_notifications = new Dictionary();
}
- public event EventHandler? NotificationActivated;
+ public event EventHandler? NotificationActivated
+ {
+ add
+ {
+ _notificationActivatedHandler += value;
+ ProcessLaunchAction();
+ }
+ remove => _notificationActivatedHandler -= value;
+ }
+
public event EventHandler? NotificationDismissed;
public async ValueTask Initialize()
@@ -33,31 +46,14 @@ namespace DesktopNotifications.Windows
_launchActionPromise = new TaskCompletionSource();
ToastNotificationManagerCompat.OnActivated += OnAppActivated;
- var launchAction = await _launchActionPromise.Task;
+ _launchAction = await _launchActionPromise.Task;
- Debug.Assert(launchAction != null);
+ Debug.Assert(_launchAction != null);
- //TODO: Lookup notification object from history?
- NotificationActivated?.Invoke(this,
- new NotificationActivatedEventArgs(null, launchAction));
+ ProcessLaunchAction();
}
}
- private static XmlDocument GenerateXml(Notification notification)
- {
- var builder = new ToastContentBuilder();
-
- builder.AddText(notification.Title);
- builder.AddText(notification.Body);
-
- foreach (var (title, actionId) in notification.Buttons)
- {
- builder.AddButton(title, ToastActivationType.Foreground, actionId);
- }
-
- return builder.GetXml();
- }
-
public ValueTask ShowNotification(Notification notification, DateTimeOffset? expirationTime)
{
if (expirationTime < DateTimeOffset.Now)
@@ -81,6 +77,39 @@ namespace DesktopNotifications.Windows
return default;
}
+ 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;
+ }
+
+ private static XmlDocument GenerateXml(Notification notification)
+ {
+ var builder = new ToastContentBuilder();
+
+ builder.AddText(notification.Title);
+ builder.AddText(notification.Body);
+
+ foreach (var (title, actionId) in notification.Buttons)
+ {
+ builder.AddButton(title, ToastActivationType.Foreground, actionId);
+ }
+
+ return builder.GetXml();
+ }
+
private void OnAppActivated(ToastNotificationActivatedEventArgsCompat e)
{
Debug.Assert(_launchActionPromise != null);
@@ -114,11 +143,7 @@ namespace DesktopNotifications.Windows
var notification = _notifications[sender];
var actionId = string.IsNullOrEmpty(activationArgs.Arguments) ? "default" : activationArgs.Arguments;
- NotificationActivated?.Invoke(this, new NotificationActivatedEventArgs(notification, actionId));
- }
-
- public void Dispose()
- {
+ _notificationActivatedHandler?.Invoke(this, new NotificationActivatedEventArgs(notification, actionId));
}
}
}
\ No newline at end of file
diff --git a/DesktopNotifications/ApplicationContext.cs b/DesktopNotifications/ApplicationContext.cs
new file mode 100644
index 0000000..6afc75e
--- /dev/null
+++ b/DesktopNotifications/ApplicationContext.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DesktopNotifications
+{
+ ///
+ ///
+ ///
+ public class ApplicationContext
+ {
+ public ApplicationContext(string name)
+ {
+ Name = name;
+ }
+
+ ///
+ ///
+ ///
+ public string Name { get; }
+
+ }
+}
diff --git a/DesktopNotifications/Notification.cs b/DesktopNotifications/Notification.cs
index ab41fdd..caef52e 100644
--- a/DesktopNotifications/Notification.cs
+++ b/DesktopNotifications/Notification.cs
@@ -11,9 +11,9 @@ namespace DesktopNotifications
Buttons = new List<(string Title, string ActionId)>();
}
- public string Title { get; set; }
+ public string? Title { get; set; }
- public string Body { get; set; }
+ public string? Body { get; set; }
public List<(string Title, string ActionId)> Buttons { get; }
}
diff --git a/Example/Program.cs b/Example/Program.cs
index 89f9dbe..88f0bc9 100644
--- a/Example/Program.cs
+++ b/Example/Program.cs
@@ -1,12 +1,9 @@
using System;
-using System.Diagnostics;
-using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using DesktopNotifications;
using DesktopNotifications.FreeDesktop;
using DesktopNotifications.Windows;
-using Example.Win32;
namespace Example
{
@@ -25,24 +22,7 @@ namespace Example
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
- const string AppName = "DesktopNotificationsExample";
-
- SetCurrentProcessExplicitAppUserModelID(AppName);
-
- using var shortcut = new ShellLink
- {
- TargetPath = Process.GetCurrentProcess().MainModule.FileName,
- Arguments = string.Empty,
- AppUserModelID = AppName
- };
-
- var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
- var startMenuPath = Path.Combine(appData, @"Microsoft\Windows\Start Menu\Programs");
- var shortcutFile = Path.Combine(startMenuPath, $"{AppName}.lnk");
-
- shortcut.Save(shortcutFile);
-
- return new WindowsNotificationManager(AppName);
+ return new WindowsNotificationManager();
}
throw new PlatformNotSupportedException();
@@ -51,12 +31,11 @@ namespace Example
private static async Task Main(string[] args)
{
using var manager = CreateManager();
+ await manager.Initialize();
manager.NotificationActivated += ManagerOnNotificationActivated;
manager.NotificationDismissed += ManagerOnNotificationDismissed;
- await manager.Initialize();
-
var notification = new Notification
{
Title = "Hello World!",