Skip to content

Commit 3d555e7

Browse files
committed
Add new api function to show message with button
1 parent d313812 commit 3d555e7

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ public interface IPublicAPI
8484
/// <param name="subTitle">Optional message subtitle</param>
8585
void ShowMsgError(string title, string subTitle = "");
8686

87+
/// <summary>
88+
/// Show the error message using Flow's standard error icon.
89+
/// </summary>
90+
/// <param name="title">Message title</param>
91+
/// <param name="buttonText">Message button content</param>
92+
/// <param name="buttonAction">Message button action</param>
93+
/// <param name="subTitle">Optional message subtitle</param>
94+
void ShowMsgErrorWithButton(string title, string buttonText, Action buttonAction, string subTitle = "");
95+
8796
/// <summary>
8897
/// Show the MainWindow when hiding
8998
/// </summary>
@@ -127,6 +136,27 @@ public interface IPublicAPI
127136
/// <param name="useMainWindowAsOwner">when true will use main windows as the owner</param>
128137
void ShowMsg(string title, string subTitle, string iconPath, bool useMainWindowAsOwner = true);
129138

139+
/// <summary>
140+
/// Show message box with button
141+
/// </summary>
142+
/// <param name="title">Message title</param>
143+
/// <param name="buttonText">Message button content</param>
144+
/// <param name="buttonAction">Message button action</param>
145+
/// <param name="subTitle">Message subtitle</param>
146+
/// <param name="iconPath">Message icon path (relative path to your plugin folder)</param>
147+
void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle = "", string iconPath = "");
148+
149+
/// <summary>
150+
/// Show message box with button
151+
/// </summary>
152+
/// <param name="title">Message title</param>
153+
/// <param name="buttonText">Message button content</param>
154+
/// <param name="buttonAction">Message button action</param>
155+
/// <param name="subTitle">Message subtitle</param>
156+
/// <param name="iconPath">Message icon path (relative path to your plugin folder)</param>
157+
/// <param name="useMainWindowAsOwner">when true will use main windows as the owner</param>
158+
void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath, bool useMainWindowAsOwner = true);
159+
130160
/// <summary>
131161
/// Open setting dialog
132162
/// </summary>

Flow.Launcher/App.xaml.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ await API.StopwatchLogInfoAsync(ClassName, "Startup cost", async () =>
171171
Current.Resources["SettingWindowFont"] = new FontFamily(_settings.SettingWindowFont);
172172
Current.Resources["ContentControlThemeFontFamily"] = new FontFamily(_settings.SettingWindowFont);
173173

174+
Notification.Install();
175+
174176
Ioc.Default.GetRequiredService<Portable>().PreStartCleanUpAfterPortabilityUpdate();
175177

176178
API.LogInfo(ClassName, "Begin Flow Launcher startup ----------------------------------------------------");

Flow.Launcher/Notification.cs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Flow.Launcher.Infrastructure;
22
using Microsoft.Toolkit.Uwp.Notifications;
33
using System;
4+
using System.Collections.Generic;
45
using System.IO;
56
using System.Windows;
67

@@ -12,10 +13,31 @@ internal static class Notification
1213

1314
internal static bool legacy = !Win32Helper.IsNotificationSupported();
1415

16+
private static readonly Dictionary<string, Action> _notificationActions = new();
17+
18+
internal static void Install()
19+
{
20+
if (!legacy)
21+
{
22+
ToastNotificationManagerCompat.OnActivated += toastArgs =>
23+
{
24+
var actionId = toastArgs.Argument; // Or use toastArgs.UserInput if using input
25+
if (_notificationActions.TryGetValue(actionId, out var action))
26+
{
27+
action?.Invoke();
28+
_notificationActions.Remove(actionId);
29+
}
30+
};
31+
}
32+
}
33+
1534
internal static void Uninstall()
1635
{
1736
if (!legacy)
37+
{
38+
_notificationActions.Clear();
1839
ToastNotificationManagerCompat.Uninstall();
40+
}
1941
}
2042

2143
public static void Show(string title, string subTitle, string iconPath = null)
@@ -67,5 +89,58 @@ private static void LegacyShow(string title, string subTitle, string iconPath)
6789
var msg = new Msg();
6890
msg.Show(title, subTitle, iconPath);
6991
}
92+
93+
public static void ShowWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath = null)
94+
{
95+
Application.Current.Dispatcher.Invoke(() =>
96+
{
97+
ShowInternalWithButton(title, buttonText, buttonAction, subTitle, iconPath);
98+
});
99+
}
100+
101+
private static void ShowInternalWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath = null)
102+
{
103+
// Handle notification for win7/8/early win10
104+
if (legacy)
105+
{
106+
LegacyShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
107+
return;
108+
}
109+
110+
// Using Windows Notification System
111+
var Icon = !File.Exists(iconPath)
112+
? Path.Combine(Constant.ProgramDirectory, "Images\\app.png")
113+
: iconPath;
114+
115+
try
116+
{
117+
var guid = Guid.NewGuid().ToString();
118+
new ToastContentBuilder()
119+
.AddText(title, hintMaxLines: 1)
120+
.AddText(subTitle)
121+
.AddButton(buttonText, ToastActivationType.Background, guid)
122+
.AddAppLogoOverride(new Uri(Icon))
123+
.Show();
124+
_notificationActions.Add(guid, buttonAction);
125+
}
126+
catch (InvalidOperationException e)
127+
{
128+
// Temporary fix for the Windows 11 notification issue
129+
// Possibly from 22621.1413 or 22621.1485, judging by post time of #2024
130+
App.API.LogException(ClassName, "Notification InvalidOperationException Error", e);
131+
LegacyShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
132+
}
133+
catch (Exception e)
134+
{
135+
App.API.LogException(ClassName, "Notification Error", e);
136+
LegacyShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
137+
}
138+
}
139+
140+
private static void LegacyShowWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath)
141+
{
142+
var msg = new MsgWithButton();
143+
msg.Show(title, buttonText, buttonAction, subTitle, iconPath);
144+
}
70145
}
71146
}

Flow.Launcher/PublicAPIInstance.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ public void SaveAppAllSettings()
123123
public void ShowMsgError(string title, string subTitle = "") =>
124124
ShowMsg(title, subTitle, Constant.ErrorIcon, true);
125125

126+
public void ShowMsgErrorWithButton(string title, string buttonText, Action buttonAction, string subTitle = "") =>
127+
ShowMsgWithButton(title, buttonText, buttonAction, subTitle, Constant.ErrorIcon, true);
128+
126129
public void ShowMsg(string title, string subTitle = "", string iconPath = "") =>
127130
ShowMsg(title, subTitle, iconPath, true);
128131

@@ -131,6 +134,14 @@ public void ShowMsg(string title, string subTitle, string iconPath, bool useMain
131134
Notification.Show(title, subTitle, iconPath);
132135
}
133136

137+
public void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle = "", string iconPath = "") =>
138+
ShowMsgWithButton(title, buttonText, buttonAction, subTitle, iconPath, true);
139+
140+
public void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath, bool useMainWindowAsOwner = true)
141+
{
142+
Notification.ShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
143+
}
144+
134145
public void OpenSettingDialog()
135146
{
136147
Application.Current.Dispatcher.Invoke(() =>

0 commit comments

Comments
 (0)