diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
index 42a1ac9b8..a89d9df21 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
@@ -30,6 +30,11 @@
This plugin is already installed
Plugin Manifest Download Failed
Please check if you can connect to github.com. This error means you may not be able to install or update plugins.
+ Update all plugins
+ Would you like to update all plugins?
+ Would you like to update {0} plugins?{1}Flow Launcher will restart after updating all plugins.
+ Would you like to update {0} plugins?
+ {0} plugins successfully updated. Restarting Flow, please wait...
Plugin {0} successfully updated. Restarting Flow, please wait...
Installing from an unknown source
You are installing this plugin from an unknown source and it may contain potential risks!{0}{0}Please ensure you understand where this plugin is from and that it is safe.{0}{0}Would you like to continue still?{0}{0}(You can switch off this warning via settings)
@@ -37,6 +42,7 @@
Plugin {0} successfully installed. Please restart Flow.
Plugin {0} successfully uninstalled. Please restart Flow.
Plugin {0} successfully updated. Please restart Flow.
+ {0} plugins successfully updated. Please restart Flow.
Plugin {0} has already been modified. Please restart Flow before making any further changes.
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index 00f77f872..8cd58ac52 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -7,6 +7,7 @@ using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin.SharedCommands;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
@@ -59,7 +60,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.InstallCommand} ",
Action = _ =>
{
- Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.InstallCommand} ");
+ Context.API.ChangeQuery(
+ $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.InstallCommand} ");
return false;
}
},
@@ -70,7 +72,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UninstallCommand} ",
Action = _ =>
{
- Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UninstallCommand} ");
+ Context.API.ChangeQuery(
+ $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UninstallCommand} ");
return false;
}
},
@@ -81,7 +84,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UpdateCommand} ",
Action = _ =>
{
- Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UpdateCommand} ");
+ Context.API.ChangeQuery(
+ $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UpdateCommand} ");
return false;
}
}
@@ -120,14 +124,14 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (Settings.AutoRestartAfterChanging)
{
message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_prompt"),
- plugin.Name, plugin.Author,
- Environment.NewLine, Environment.NewLine);
+ plugin.Name, plugin.Author,
+ Environment.NewLine, Environment.NewLine);
}
else
{
message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_prompt_no_restart"),
- plugin.Name, plugin.Author,
- Environment.NewLine);
+ plugin.Name, plugin.Author,
+ Environment.NewLine);
}
if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_install_title"),
@@ -154,44 +158,47 @@ namespace Flow.Launcher.Plugin.PluginsManager
}
catch (HttpRequestException e)
{
- Context.API.ShowMsgError(string.Format(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), plugin.Name),
- Context.API.GetTranslation("plugin_pluginsmanager_download_error"));
+ Context.API.ShowMsgError(
+ string.Format(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), plugin.Name),
+ Context.API.GetTranslation("plugin_pluginsmanager_download_error"));
Log.Exception("PluginsManager", "An error occurred while downloading plugin", e);
return;
}
catch (Exception e)
{
Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
- string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"),
- plugin.Name));
+ string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"),
+ plugin.Name));
Log.Exception("PluginsManager", "An error occurred while downloading plugin", e);
return;
}
-
+
if (Settings.AutoRestartAfterChanging)
{
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_installing_plugin"),
- string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_success_restart"),
- plugin.Name));
+ string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_success_restart"),
+ plugin.Name));
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));
+ string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_success_no_restart"),
+ plugin.Name));
}
}
- internal async ValueTask> RequestUpdateAsync(string search, CancellationToken token, bool usePrimaryUrlOnly = false)
+ internal async ValueTask> RequestUpdateAsync(string search, CancellationToken token,
+ bool usePrimaryUrlOnly = false)
{
await PluginsManifest.UpdateManifestAsync(token, usePrimaryUrlOnly);
- var resultsForUpdate =
+ var resultsForUpdate = (
from existingPlugin in Context.API.GetAllPlugins()
join pluginFromManifest in PluginsManifest.UserPlugins
on existingPlugin.Metadata.ID equals pluginFromManifest.ID
- where existingPlugin.Metadata.Version.CompareTo(pluginFromManifest.Version) <
+ where String.Compare(existingPlugin.Metadata.Version, pluginFromManifest.Version,
+ StringComparison.InvariantCulture) <
0 // if current version precedes manifest version
&& !PluginManager.PluginModified(existingPlugin.Metadata.ID)
select
@@ -204,7 +211,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
existingPlugin.Metadata.IcoPath,
PluginExistingMetadata = existingPlugin.Metadata,
PluginNewUserPlugin = pluginFromManifest
- };
+ }).ToList();
if (!resultsForUpdate.Any())
return new List
@@ -226,76 +233,169 @@ namespace Flow.Launcher.Plugin.PluginsManager
IcoPath = x.IcoPath,
Action = e =>
{
-
string message;
if (Settings.AutoRestartAfterChanging)
{
- message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_update_prompt"),
- x.Name, x.Author,
- Environment.NewLine, Environment.NewLine);
+ message = string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_update_prompt"),
+ x.Name, x.Author,
+ Environment.NewLine, Environment.NewLine);
}
else
{
- message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_update_prompt_no_restart"),
- x.Name, x.Author,
- Environment.NewLine);
+ message = string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_update_prompt_no_restart"),
+ x.Name, x.Author,
+ Environment.NewLine);
}
if (MessageBox.Show(message,
Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
- MessageBoxButton.YesNo) == MessageBoxResult.Yes)
+ MessageBoxButton.YesNo) != MessageBoxResult.Yes)
{
- var downloadToFilePath = Path.Combine(Path.GetTempPath(),
- $"{x.Name}-{x.NewVersion}.zip");
-
- _ = Task.Run(async delegate
- {
- if (File.Exists(downloadToFilePath))
- {
- File.Delete(downloadToFilePath);
- }
-
- await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath)
- .ConfigureAwait(false);
-
- PluginManager.UpdatePlugin(x.PluginExistingMetadata, x.PluginNewUserPlugin, downloadToFilePath);
-
- if (Settings.AutoRestartAfterChanging)
- {
- Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
- string.Format(Context.API.GetTranslation("plugin_pluginsmanager_update_success_restart"),
- x.Name));
- Context.API.RestartApp();
- }
- else
- {
- Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
- string.Format(Context.API.GetTranslation("plugin_pluginsmanager_update_success_no_restart"),
- x.Name));
- }
- }).ContinueWith(t =>
- {
- Log.Exception("PluginsManager", $"Update failed for {x.Name}",
- t.Exception.InnerException);
- Context.API.ShowMsg(
- Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
- string.Format(
- Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"),
- x.Name));
- }, TaskContinuationOptions.OnlyOnFaulted);
-
- return true;
+ return false;
}
- return false;
+ var downloadToFilePath = Path.Combine(Path.GetTempPath(),
+ $"{x.Name}-{x.NewVersion}.zip");
+
+ _ = Task.Run(async delegate
+ {
+ if (File.Exists(downloadToFilePath))
+ {
+ File.Delete(downloadToFilePath);
+ }
+
+ await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath)
+ .ConfigureAwait(false);
+
+ PluginManager.UpdatePlugin(x.PluginExistingMetadata, x.PluginNewUserPlugin,
+ downloadToFilePath);
+
+ if (Settings.AutoRestartAfterChanging)
+ {
+ Context.API.ShowMsg(
+ Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
+ string.Format(
+ Context.API.GetTranslation(
+ "plugin_pluginsmanager_update_success_restart"),
+ x.Name));
+ Context.API.RestartApp();
+ }
+ else
+ {
+ Context.API.ShowMsg(
+ Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
+ string.Format(
+ Context.API.GetTranslation(
+ "plugin_pluginsmanager_update_success_no_restart"),
+ x.Name));
+ }
+ }).ContinueWith(t =>
+ {
+ Log.Exception("PluginsManager", $"Update failed for {x.Name}",
+ t.Exception.InnerException);
+ Context.API.ShowMsg(
+ Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
+ string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"),
+ x.Name));
+ }, TaskContinuationOptions.OnlyOnFaulted);
+
+ return true;
+
},
ContextData =
new UserPlugin
{
- Website = x.PluginNewUserPlugin.Website, UrlSourceCode = x.PluginNewUserPlugin.UrlSourceCode
+ Website = x.PluginNewUserPlugin.Website,
+ UrlSourceCode = x.PluginNewUserPlugin.UrlSourceCode
}
});
+ // Update all result
+ if (resultsForUpdate.Count() > 1)
+ {
+ var updateAllResult = new Result
+ {
+ Title = Context.API.GetTranslation("plugin_pluginsmanager_update_all_title"),
+ SubTitle = Context.API.GetTranslation("plugin_pluginsmanager_update_all_subtitle"),
+ IcoPath = icoPath,
+ AsyncAction = async e =>
+ {
+ string message;
+ if (Settings.AutoRestartAfterChanging)
+ {
+ message = string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_update_all_prompt"),
+ resultsForUpdate.Count(), Environment.NewLine);
+ }
+ else
+ {
+ message = string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_update_all_prompt_no_restart"),
+ resultsForUpdate.Count());
+ }
+
+ if (MessageBox.Show(message,
+ Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
+ MessageBoxButton.YesNo) == MessageBoxResult.No)
+ {
+ return false;
+ }
+
+ await Task.WhenAll(resultsForUpdate.Select(async plugin =>
+ {
+ var downloadToFilePath = Path.Combine(Path.GetTempPath(),
+ $"{plugin.Name}-{plugin.NewVersion}.zip");
+
+ try
+ {
+ if (File.Exists(downloadToFilePath))
+ {
+ File.Delete(downloadToFilePath);
+ }
+
+ await Http.DownloadAsync(plugin.PluginNewUserPlugin.UrlDownload, downloadToFilePath)
+ .ConfigureAwait(false);
+
+ PluginManager.UpdatePlugin(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin,
+ downloadToFilePath);
+ }
+ catch (Exception ex)
+ {
+ Log.Exception("PluginsManager", $"Update failed for {plugin.Name}", ex.InnerException);
+ Context.API.ShowMsg(
+ Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
+ string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"),
+ plugin.Name));
+ }
+ }));
+
+ if (Settings.AutoRestartAfterChanging)
+ {
+ Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
+ string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_update_all_success_restart"),
+ resultsForUpdate.Count()));
+ Context.API.RestartApp();
+ }
+ else
+ {
+ Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
+ string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_update_all_success_no_restart"),
+ resultsForUpdate.Count()));
+ }
+
+ return true;
+ },
+ ContextData = new UserPlugin()
+ };
+ results = results.Prepend(updateAllResult);
+ }
+
return Search(results, search);
}
@@ -351,9 +451,11 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (Settings.WarnFromUnknownSource)
{
if (!InstallSourceKnown(plugin.UrlDownload)
- && MessageBox.Show(string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_unknown_source_warning"),
+ && MessageBox.Show(string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_install_unknown_source_warning"),
Environment.NewLine),
- Context.API.GetTranslation("plugin_pluginsmanager_install_unknown_source_warning_title"),
+ Context.API.GetTranslation(
+ "plugin_pluginsmanager_install_unknown_source_warning_title"),
MessageBoxButton.YesNo) == MessageBoxResult.No)
return false;
}
@@ -365,10 +467,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
}
};
- return new List
- {
- result
- };
+ return new List { result };
}
private bool InstallSourceKnown(string url)
@@ -377,10 +476,12 @@ namespace Flow.Launcher.Plugin.PluginsManager
var acceptedSource = "https://github.com";
var constructedUrlPart = string.Format("{0}/{1}/", acceptedSource, author);
- return url.StartsWith(acceptedSource) && Context.API.GetAllPlugins().Any(x => x.Metadata.Website.StartsWith(constructedUrlPart));
+ return url.StartsWith(acceptedSource) &&
+ Context.API.GetAllPlugins().Any(x => x.Metadata.Website.StartsWith(constructedUrlPart));
}
- internal async ValueTask> RequestInstallOrUpdate(string search, CancellationToken token, bool usePrimaryUrlOnly = false)
+ internal async ValueTask> RequestInstallOrUpdate(string search, CancellationToken token,
+ bool usePrimaryUrlOnly = false)
{
await PluginsManifest.UpdateManifestAsync(token, usePrimaryUrlOnly);
@@ -419,7 +520,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
private void Install(UserPlugin plugin, string downloadedFilePath)
{
if (!File.Exists(downloadedFilePath))
- throw new FileNotFoundException($"Plugin {plugin.ID} zip file not found at {downloadedFilePath}", downloadedFilePath);
+ throw new FileNotFoundException($"Plugin {plugin.ID} zip file not found at {downloadedFilePath}",
+ downloadedFilePath);
try
{
PluginManager.InstallPlugin(plugin, downloadedFilePath);
@@ -428,18 +530,21 @@ namespace Flow.Launcher.Plugin.PluginsManager
catch (FileNotFoundException e)
{
Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
- Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile"));
+ Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile"));
Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e);
}
catch (InvalidOperationException e)
{
Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
- string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_duplicate"), plugin.Name));
+ string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_duplicate"),
+ plugin.Name));
Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e);
}
- catch (ArgumentException e) {
+ catch (ArgumentException e)
+ {
Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
- string.Format(Context.API.GetTranslation("plugin_pluginsmanager_plugin_modified_error"), plugin.Name));
+ string.Format(Context.API.GetTranslation("plugin_pluginsmanager_plugin_modified_error"),
+ plugin.Name));
Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e);
}
}
@@ -459,15 +564,17 @@ namespace Flow.Launcher.Plugin.PluginsManager
string message;
if (Settings.AutoRestartAfterChanging)
{
- message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_prompt"),
- x.Metadata.Name, x.Metadata.Author,
- Environment.NewLine, Environment.NewLine);
+ message = string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_uninstall_prompt"),
+ x.Metadata.Name, x.Metadata.Author,
+ Environment.NewLine, Environment.NewLine);
}
else
{
- message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_prompt_no_restart"),
- x.Metadata.Name, x.Metadata.Author,
- Environment.NewLine);
+ message = string.Format(
+ Context.API.GetTranslation("plugin_pluginsmanager_uninstall_prompt_no_restart"),
+ x.Metadata.Name, x.Metadata.Author,
+ Environment.NewLine);
}
if (MessageBox.Show(message,
@@ -482,9 +589,12 @@ namespace Flow.Launcher.Plugin.PluginsManager
}
else
{
- Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_title"),
- string.Format(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_success_no_restart"),
- x.Metadata.Name));
+ Context.API.ShowMsg(
+ Context.API.GetTranslation("plugin_pluginsmanager_uninstall_title"),
+ string.Format(
+ Context.API.GetTranslation(
+ "plugin_pluginsmanager_uninstall_success_no_restart"),
+ x.Metadata.Name));
}
return true;
@@ -501,13 +611,13 @@ namespace Flow.Launcher.Plugin.PluginsManager
{
try
{
- PluginManager.UninstallPlugin(plugin, removeSettings:true);
+ PluginManager.UninstallPlugin(plugin, removeSettings: true);
}
catch (ArgumentException e)
{
Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e);
Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_error_title"),
- Context.API.GetTranslation("plugin_pluginsmanager_plugin_modified_error"));
+ Context.API.GetTranslation("plugin_pluginsmanager_plugin_modified_error"));
}
}
}