diff --git a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs index 9d6174eb7ee..249eeac9757 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 ShowMsg(string title, string subTitle, string iconPath, bool useMainWindowAsOwner = true, bool forceShown = false) + { + _api.ShowMsg(title, subTitle, iconPath, useMainWindowAsOwner, forceShown); + } + public void OpenSettingDialog() { _api.OpenSettingDialog(); diff --git a/Flow.Launcher.Core/Plugin/PluginInstaller.cs b/Flow.Launcher.Core/Plugin/PluginInstaller.cs index 6027b712e73..47a250a364f 100644 --- a/Flow.Launcher.Core/Plugin/PluginInstaller.cs +++ b/Flow.Launcher.Core/Plugin/PluginInstaller.cs @@ -99,7 +99,9 @@ await DownloadFileAsync( { PublicApi.Instance.ShowMsg( Localize.installbtn(), - Localize.InstallSuccessNoRestart(newPlugin.Name)); + Localize.InstallSuccessNoRestart(newPlugin.Name), + iconPath: "", + forceShown: true); } } @@ -194,7 +196,9 @@ public static async Task UninstallPluginAndCheckRestartAsync(PluginMetadata oldP { PublicApi.Instance.ShowMsg( Localize.uninstallbtn(), - Localize.UninstallSuccessNoRestart(oldPlugin.Name)); + Localize.UninstallSuccessNoRestart(oldPlugin.Name), + iconPath: "", + forceShown: true); } } @@ -254,7 +258,9 @@ await DownloadFileAsync( { PublicApi.Instance.ShowMsg( Localize.updatebtn(), - Localize.UpdateSuccessNoRestart(newPlugin.Name)); + Localize.UpdateSuccessNoRestart(newPlugin.Name), + iconPath: "", + forceShown: true); } } @@ -298,7 +304,8 @@ where string.Compare(existingPlugin.Metadata.Version, pluginUpdateSource.Version { if (!silentUpdate) { - PublicApi.Instance.ShowMsg(Localize.updateNoResultTitle(), Localize.updateNoResultSubtitle()); + PublicApi.Instance.ShowMsg(Localize.updateNoResultTitle(), Localize.updateNoResultSubtitle(), iconPath: "", + forceShown: true); } return; } @@ -370,7 +377,9 @@ await DownloadFileAsync( { PublicApi.Instance.ShowMsg( Localize.updatebtn(), - Localize.PluginsUpdateSuccessNoRestart()); + Localize.PluginsUpdateSuccessNoRestart(), + iconPath: "", + forceShown: true); } } diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 78464ddc9ba..167e77ba157 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -312,11 +312,9 @@ public static async Task InitializePluginsAsync(IResultUpdateRegister register) if (!_initFailedPlugins.IsEmpty) { var failed = string.Join(",", _initFailedPlugins.Values.Select(x => x.Metadata.Name)); - PublicApi.Instance.ShowMsg( + PublicApi.Instance.ShowMsgError( Localize.failedToInitializePluginsTitle(), - Localize.failedToInitializePluginsMessage(failed), - "", - false + Localize.failedToInitializePluginsMessage(failed) ); } } diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 1f138e843e8..a9380efbe79 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -42,7 +42,7 @@ public async Task UpdateAppAsync(bool silentUpdate = true) { if (!silentUpdate) _api.ShowMsg(Localize.pleaseWait(), - Localize.update_flowlauncher_update_check()); + Localize.update_flowlauncher_update_check(), iconPath: "", forceShown: true); using var updateManager = await GitHubUpdateManagerAsync(GitHubRepository).ConfigureAwait(false); @@ -64,7 +64,7 @@ public async Task UpdateAppAsync(bool silentUpdate = true) if (!silentUpdate) _api.ShowMsg(Localize.update_flowlauncher_update_found(), - Localize.update_flowlauncher_updating()); + Localize.update_flowlauncher_updating(), iconPath: "", forceShown: true); await updateManager.DownloadReleases(newUpdateInfo.ReleasesToApply).ConfigureAwait(false); diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index fd535f21a6e..00094a5cd73 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -511,6 +511,7 @@ public bool KeepMaxResults public bool DontPromptUpdateMsg { get; set; } public bool EnableUpdateLog { get; set; } + public bool EnableSuccessNotification { get; set; } = true; public bool StartFlowLauncherOnSystemStartup { get; set; } = false; public bool UseLogonTaskForStartup { get; set; } = false; diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 62ed58930e5..593cfde8fea 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -136,6 +136,16 @@ public interface IPublicAPI /// when true will use main windows as the owner void ShowMsg(string title, string subTitle, string iconPath, bool useMainWindowAsOwner = true); + /// + /// Show message box + /// + /// Message title + /// Message subtitle + /// Message icon path (relative path to your plugin folder) + /// when true will use main windows as the owner + /// when true will force the message to be shown regardless of user settings of `Show success notifications` + void ShowMsg(string title, string subTitle, string iconPath, bool useMainWindowAsOwner = true, bool forceShown = false); + /// /// Show message box with button /// @@ -162,7 +172,6 @@ public interface IPublicAPI /// void OpenSettingDialog(); - /// /// Open plugin setting window for a specific plugin. /// Reuses the existing window when that plugin's settings window is already open. diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index dae6ee81b15..2a1be04d69f 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -125,6 +125,8 @@ Flow Launcher search window is hidden in the tray after starting up. Hide tray icon When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. + Show success notifications + Show success notifications for completed actions like copying text. When disabled, only errors and important alerts will appear. Ignore accents when searching Treat accented and unaccented characters as equivalent. Would you like to turn on the option to ignore accents when searching? diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 25c6d788a85..3d9aa9dab32 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -53,7 +53,7 @@ public class PublicAPIInstance : IPublicAPI, IRemovable private Updater _updater; private Updater Updater => _updater ??= Ioc.Default.GetRequiredService(); - private readonly object _saveSettingsLock = new(); + private readonly Lock _saveSettingsLock = new(); #region Constructor @@ -119,21 +119,30 @@ public void SaveAppAllSettings() public Task ReloadAllPluginData() => PluginManager.ReloadDataAsync(); public void ShowMsgError(string title, string subTitle = "") => - ShowMsg(title, subTitle, Constant.ErrorIcon, true); + ShowMsg(title, subTitle, Constant.ErrorIcon, useMainWindowAsOwner: true, forceShown:true); public void ShowMsgErrorWithButton(string title, string buttonText, Action buttonAction, string subTitle = "") => - ShowMsgWithButton(title, buttonText, buttonAction, subTitle, Constant.ErrorIcon, true); + ShowMsgWithButton(title, buttonText, buttonAction, subTitle, Constant.ErrorIcon, useMainWindowAsOwner: true); public void ShowMsg(string title, string subTitle = "", string iconPath = "") => - ShowMsg(title, subTitle, iconPath, true); + ShowMsg(title, subTitle, iconPath, useMainWindowAsOwner:true, forceShown:false); - public void ShowMsg(string title, string subTitle, string iconPath, bool useMainWindowAsOwner = true) + public void ShowMsg(string title, string subTitle, string iconPath, bool useMainWindowAsOwner = true) => + ShowMsg(title, subTitle, iconPath, useMainWindowAsOwner: true, forceShown: false); + + public void ShowMsg(string title, string subTitle, string iconPath, bool useMainWindowAsOwner = true, bool forceShown = false) { + if (!forceShown && !_settings.EnableSuccessNotification && + !string.Equals(iconPath, Constant.ErrorIcon, StringComparison.OrdinalIgnoreCase)) + { + return; + } + 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); + ShowMsgWithButton(title, buttonText, buttonAction, subTitle, iconPath, useMainWindowAsOwner: true); public void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath, bool useMainWindowAsOwner = true) { diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 5779071534f..f40a68c2757 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -92,6 +92,20 @@ OnContent="{DynamicResource enable}" /> + + + + + + + + PromptDownloadIfNotInstallAsync(string installe } api.ShowMsg(Localize.flowlauncher_plugin_everything_installing_title(), - Localize.flowlauncher_plugin_everything_installing_subtitle(), "", useMainWindowAsOwner: false); + Localize.flowlauncher_plugin_everything_installing_subtitle(), iconPath: "", useMainWindowAsOwner: false, forceShown: true); await DroplexPackage.Drop(App.Everything1_4_1_1009).ConfigureAwait(false); api.ShowMsg(Localize.flowlauncher_plugin_everything_installing_title(), - Localize.flowlauncher_plugin_everything_installationsuccess_subtitle(), "", useMainWindowAsOwner: false); + Localize.flowlauncher_plugin_everything_installationsuccess_subtitle(), iconPath: "", useMainWindowAsOwner: false, forceShown: true); installedLocation = "C:\\Program Files\\Everything\\Everything.exe"; diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index efbe8d7ba7d..7586644b690 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -110,7 +110,7 @@ internal async Task InstallOrUpdateAsync(UserPlugin plugin) return; } - Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_alreadyexists")); + Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_update_alreadyexists")); return; } @@ -194,14 +194,18 @@ await DownloadFileAsync( { Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_installing_plugin"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_success_restart"), - plugin.Name)); + plugin.Name), + iconPath: "", + forceShown: true); Context.API.RestartApp(); } else { Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_installing_plugin"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_success_no_restart"), - plugin.Name)); + plugin.Name), + iconPath: "", + forceShown: true); } } @@ -383,7 +387,9 @@ await DownloadFileAsync( string.Format( Context.API.GetTranslation( "plugin_pluginsmanager_update_success_restart"), - x.Name)); + x.Name), + iconPath: "", + forceShown: true); Context.API.RestartApp(); } else @@ -393,7 +399,9 @@ await DownloadFileAsync( string.Format( Context.API.GetTranslation( "plugin_pluginsmanager_update_success_no_restart"), - x.Name)); + x.Name), + iconPath: "", + forceShown: true); } } } @@ -510,7 +518,9 @@ await DownloadFileAsync( Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_title"), string.Format( Context.API.GetTranslation("plugin_pluginsmanager_update_all_success_restart"), - resultsForUpdate.Count)); + resultsForUpdate.Count), + iconPath: "", + forceShown: true); Context.API.RestartApp(); } else @@ -518,7 +528,9 @@ await DownloadFileAsync( Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_title"), string.Format( Context.API.GetTranslation("plugin_pluginsmanager_update_all_success_no_restart"), - resultsForUpdate.Count)); + resultsForUpdate.Count), + iconPath: "", + forceShown: true); } return true; @@ -809,7 +821,9 @@ internal List RequestUninstall(string search) string.Format( Context.API.GetTranslation( "plugin_pluginsmanager_uninstall_success_no_restart"), - x.Metadata.Name)); + x.Metadata.Name), + iconPath: "", + forceShown: true); } return true;