diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index cb60251ed..76c7a4911 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -84,6 +84,15 @@ namespace Flow.Launcher.Plugin
/// Optional message subtitle
void ShowMsgError(string title, string subTitle = "");
+ ///
+ /// Show the error message using Flow's standard error icon.
+ ///
+ /// Message title
+ /// Message button content
+ /// Message button action
+ /// Optional message subtitle
+ void ShowMsgErrorWithButton(string title, string buttonText, Action buttonAction, string subTitle = "");
+
///
/// Show the MainWindow when hiding
///
@@ -127,6 +136,27 @@ namespace Flow.Launcher.Plugin
/// when true will use main windows as the owner
void ShowMsg(string title, string subTitle, string iconPath, bool useMainWindowAsOwner = true);
+ ///
+ /// Show message box with button
+ ///
+ /// Message title
+ /// Message button content
+ /// Message button action
+ /// Message subtitle
+ /// Message icon path (relative path to your plugin folder)
+ void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle = "", string iconPath = "");
+
+ ///
+ /// Show message box with button
+ ///
+ /// Message title
+ /// Message button content
+ /// Message button action
+ /// Message subtitle
+ /// Message icon path (relative path to your plugin folder)
+ /// when true will use main windows as the owner
+ void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath, bool useMainWindowAsOwner = true);
+
///
/// Open setting dialog
///
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index cedced181..59e8cac20 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -171,6 +171,8 @@ namespace Flow.Launcher
Current.Resources["SettingWindowFont"] = new FontFamily(_settings.SettingWindowFont);
Current.Resources["ContentControlThemeFontFamily"] = new FontFamily(_settings.SettingWindowFont);
+ Notification.Install();
+
Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate();
API.LogInfo(ClassName, "Begin Flow Launcher startup ----------------------------------------------------");
diff --git a/Flow.Launcher/Notification.cs b/Flow.Launcher/Notification.cs
index be81e6ec6..d277c45df 100644
--- a/Flow.Launcher/Notification.cs
+++ b/Flow.Launcher/Notification.cs
@@ -1,6 +1,7 @@
using Flow.Launcher.Infrastructure;
using Microsoft.Toolkit.Uwp.Notifications;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Windows;
@@ -12,10 +13,31 @@ namespace Flow.Launcher
internal static bool legacy = !Win32Helper.IsNotificationSupported();
+ private static readonly Dictionary _notificationActions = new();
+
+ internal static void Install()
+ {
+ if (!legacy)
+ {
+ ToastNotificationManagerCompat.OnActivated += toastArgs =>
+ {
+ var actionId = toastArgs.Argument; // Or use toastArgs.UserInput if using input
+ if (_notificationActions.TryGetValue(actionId, out var action))
+ {
+ action?.Invoke();
+ _notificationActions.Remove(actionId);
+ }
+ };
+ }
+ }
+
internal static void Uninstall()
{
if (!legacy)
+ {
+ _notificationActions.Clear();
ToastNotificationManagerCompat.Uninstall();
+ }
}
public static void Show(string title, string subTitle, string iconPath = null)
@@ -67,5 +89,58 @@ namespace Flow.Launcher
var msg = new Msg();
msg.Show(title, subTitle, iconPath);
}
+
+ public static void ShowWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath = null)
+ {
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ ShowInternalWithButton(title, buttonText, buttonAction, subTitle, iconPath);
+ });
+ }
+
+ private static void ShowInternalWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath = null)
+ {
+ // Handle notification for win7/8/early win10
+ if (legacy)
+ {
+ LegacyShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
+ return;
+ }
+
+ // Using Windows Notification System
+ var Icon = !File.Exists(iconPath)
+ ? Path.Combine(Constant.ProgramDirectory, "Images\\app.png")
+ : iconPath;
+
+ try
+ {
+ var guid = Guid.NewGuid().ToString();
+ new ToastContentBuilder()
+ .AddText(title, hintMaxLines: 1)
+ .AddText(subTitle)
+ .AddButton(buttonText, ToastActivationType.Background, guid)
+ .AddAppLogoOverride(new Uri(Icon))
+ .Show();
+ _notificationActions.Add(guid, buttonAction);
+ }
+ catch (InvalidOperationException e)
+ {
+ // Temporary fix for the Windows 11 notification issue
+ // Possibly from 22621.1413 or 22621.1485, judging by post time of #2024
+ App.API.LogException(ClassName, "Notification InvalidOperationException Error", e);
+ LegacyShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
+ }
+ catch (Exception e)
+ {
+ App.API.LogException(ClassName, "Notification Error", e);
+ LegacyShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
+ }
+ }
+
+ private static void LegacyShowWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath)
+ {
+ var msg = new MsgWithButton();
+ msg.Show(title, buttonText, buttonAction, subTitle, iconPath);
+ }
}
}
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 80d5de53d..a0e680618 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -123,6 +123,9 @@ namespace Flow.Launcher
public void ShowMsgError(string title, string subTitle = "") =>
ShowMsg(title, subTitle, Constant.ErrorIcon, true);
+ public void ShowMsgErrorWithButton(string title, string buttonText, Action buttonAction, string subTitle = "") =>
+ ShowMsgWithButton(title, buttonText, buttonAction, subTitle, Constant.ErrorIcon, true);
+
public void ShowMsg(string title, string subTitle = "", string iconPath = "") =>
ShowMsg(title, subTitle, iconPath, true);
@@ -131,6 +134,14 @@ namespace Flow.Launcher
Notification.Show(title, subTitle, iconPath);
}
+ public void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle = "", string iconPath = "") =>
+ ShowMsgWithButton(title, buttonText, buttonAction, subTitle, iconPath, true);
+
+ public void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath, bool useMainWindowAsOwner = true)
+ {
+ Notification.ShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
+ }
+
public void OpenSettingDialog()
{
Application.Current.Dispatcher.Invoke(() =>