diff --git a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs index 9d6174eb7ee..7ee4dc76e80 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs @@ -89,6 +89,11 @@ public void ShowMsg(string title, string subTitle, string iconPath, bool useMain _api.ShowMsg(title, subTitle, iconPath, useMainWindowAsOwner); } + public void ShowNotification(string title, string subTitle = "", NotificationSeverity severity = NotificationSeverity.Informational) + { + _api.ShowNotification(title, subTitle, severity); + } + public void OpenSettingDialog() { _api.OpenSettingDialog(); diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 304f4d5c00e..92682bcc59a 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -93,6 +93,17 @@ public interface IPublicAPI /// Optional message subtitle void ShowMsgErrorWithButton(string title, string buttonText, Action buttonAction, string subTitle = ""); + /// + /// Show an inline notification bar in the Flow Launcher main window. + /// Unlike , this displays directly inside the application window and + /// cannot be blocked by OS notification settings. + /// The notification bar remains visible until the user closes it. + /// + /// Notification title + /// Optional notification subtitle + /// Severity level that controls the icon and accent color + void ShowNotification(string title, string subTitle = "", NotificationSeverity severity = NotificationSeverity.Informational); + /// /// Show the MainWindow when hiding /// diff --git a/Flow.Launcher.Plugin/NotificationSeverity.cs b/Flow.Launcher.Plugin/NotificationSeverity.cs new file mode 100644 index 00000000000..540805b7c41 --- /dev/null +++ b/Flow.Launcher.Plugin/NotificationSeverity.cs @@ -0,0 +1,20 @@ +namespace Flow.Launcher.Plugin +{ + /// + /// Specifies the severity level of an inline notification shown in the Flow Launcher window. + /// + public enum NotificationSeverity + { + /// Informational notification (blue icon). + Informational = 0, + + /// Success notification (green icon). + Success = 1, + + /// Warning notification (yellow icon). + Warning = 2, + + /// Error notification (red icon). + Error = 3 + } +} diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 2950d2f6555..5d470ae5dad 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -352,6 +352,16 @@ Y2="0" /> + + diff --git a/Flow.Launcher/Notification.cs b/Flow.Launcher/Notification.cs index deb5442a4b1..32464ab8565 100644 --- a/Flow.Launcher/Notification.cs +++ b/Flow.Launcher/Notification.cs @@ -2,7 +2,11 @@ using System.Collections.Concurrent; using System.IO; using System.Windows; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure; +using Flow.Launcher.Plugin; +using Flow.Launcher.ViewModel; +using iNKORE.UI.WPF.Modern.Controls; using Microsoft.Toolkit.Uwp.Notifications; namespace Flow.Launcher @@ -141,5 +145,19 @@ private static void LegacyShowWithButton(string title, string buttonText, Action var msg = new MsgWithButton(); msg.Show(title, buttonText, buttonAction, subTitle, iconPath); } + + public static void ShowInline(string title, string subTitle, NotificationSeverity severity) + { + var infoBarSeverity = severity switch + { + NotificationSeverity.Success => InfoBarSeverity.Success, + NotificationSeverity.Warning => InfoBarSeverity.Warning, + NotificationSeverity.Error => InfoBarSeverity.Error, + _ => InfoBarSeverity.Informational + }; + + var mainVM = Ioc.Default.GetRequiredService(); + mainVM.ShowInlineNotification(title, subTitle, infoBarSeverity); + } } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index d3b84b937c0..3b0bc14ead3 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -132,6 +132,11 @@ public void ShowMsg(string title, string subTitle, string iconPath, bool useMain Notification.Show(title, subTitle, iconPath); } + public void ShowNotification(string title, string subTitle = "", NotificationSeverity severity = NotificationSeverity.Informational) + { + Notification.ShowInline(title, subTitle, severity); + } + public void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle = "", string iconPath = "") => ShowMsgWithButton(title, buttonText, buttonAction, subTitle, iconPath, true); diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 920e5be256c..8827320e514 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -26,6 +26,7 @@ using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Storage; using iNKORE.UI.WPF.Modern; +using iNKORE.UI.WPF.Modern.Controls; using Microsoft.VisualStudio.Threading; namespace Flow.Launcher.ViewModel @@ -935,6 +936,25 @@ public UserControl CustomizedPreviewControl public double ClockPanelOpacity { get; set; } = 1; public double SearchIconOpacity { get; set; } = 1; + public bool InlineNotificationIsOpen { get; set; } + public string InlineNotificationTitle { get; set; } = string.Empty; + public string InlineNotificationMessage { get; set; } = string.Empty; + public InfoBarSeverity InlineNotificationSeverity { get; set; } = InfoBarSeverity.Informational; + + internal void ShowInlineNotification(string title, string message, InfoBarSeverity severity) + { + if (!Application.Current.Dispatcher.CheckAccess()) + { + Application.Current.Dispatcher.Invoke(() => ShowInlineNotification(title, message, severity)); + return; + } + + InlineNotificationTitle = title; + InlineNotificationMessage = message; + InlineNotificationSeverity = severity; + InlineNotificationIsOpen = true; + } + private string _placeholderText; public string PlaceholderText {