From 092b4593f8a30106043200fe929614f006f7f11d Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Thu, 18 Nov 2021 10:35:45 -0500 Subject: [PATCH 01/16] Detect URL and install --- .../PluginsManager.cs | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index cd1ab45715a..d87a015a9fc 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -302,6 +302,37 @@ internal List Search(IEnumerable results, string searchName) .ToList(); } + internal List InstallFromWeb(string url) + { + var fileName = url.Split("/").Last(); + var filePath = Path.Combine(DataLocation.PluginsDirectory, fileName); + var plugin = new UserPlugin + { + ID = "", + Name = fileName.Split(".").First(), + Author = "N/A", + UrlDownload = url + }; + var result = new Result + { + Title = $"{url}", + SubTitle = $"Download and Install from URL", + Action = e => + { + if (e.SpecialKeyState.CtrlPressed) + { + SearchWeb.NewTabInBrowser(url); + return ShouldHideWindow; + } + + Application.Current.MainWindow.Hide(); + _ = InstallOrUpdate(plugin); + return ShouldHideWindow; + } + }; + return new List { result }; + } + internal async ValueTask> RequestInstallOrUpdate(string searchName, CancellationToken token) { if (!PluginsManifest.UserPlugins.Any()) @@ -337,6 +368,10 @@ internal async ValueTask> RequestInstallOrUpdate(string searchName, ContextData = x }); + if (Uri.IsWellFormedUriString(searchNameWithoutKeyword, UriKind.Absolute)) + { + return InstallFromWeb(searchNameWithoutKeyword); + } return Search(results, searchNameWithoutKeyword); } @@ -372,8 +407,8 @@ private void Install(UserPlugin plugin, string downloadedFilePath) MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile")); return; } - - string newPluginPath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}-{plugin.Version}"); + var directory = String.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}" : $"{plugin.Name}-{plugin.Version}"; + string newPluginPath = Path.Combine(DataLocation.PluginsDirectory, directory); FilesFolders.CopyAll(pluginFolderPath, newPluginPath); @@ -467,4 +502,4 @@ private List AutoCompleteReturnAllResults(string search, string hotkey, return new List(); } } -} \ No newline at end of file +} From 8c50d13aa5ab5da540a9903f7c0ba2e324313505 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Thu, 18 Nov 2021 11:40:06 -0500 Subject: [PATCH 02/16] Use correct icon --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index d87a015a9fc..644309c1e01 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -317,6 +317,7 @@ internal List InstallFromWeb(string url) { Title = $"{url}", SubTitle = $"Download and Install from URL", + IcoPath = icoPath, Action = e => { if (e.SpecialKeyState.CtrlPressed) From cf056a92c04db5d310a2a83d3227aae333786d9e Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Thu, 18 Nov 2021 11:47:21 -0500 Subject: [PATCH 03/16] Filename as title for result --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 644309c1e01..fe434c4e488 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -315,7 +315,7 @@ internal List InstallFromWeb(string url) }; var result = new Result { - Title = $"{url}", + Title = fileName, SubTitle = $"Download and Install from URL", IcoPath = icoPath, Action = e => From 2e2d2591d75c137ce3ab47161db1c4bc591144fb Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Fri, 19 Nov 2021 10:59:32 -0500 Subject: [PATCH 04/16] Block install if manual install exists --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index fe434c4e488..0ebbc2fdbee 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -104,7 +104,7 @@ internal List GetDefaultHotKeys() internal async Task InstallOrUpdate(UserPlugin plugin) { - if (PluginExists(plugin.ID)) + if (PluginExists(plugin.ID) || Directory.Exists(Path.Combine(DataLocation.PluginsDirectory, plugin.Name))) { if (Context.API.GetAllPlugins() .Any(x => x.Metadata.ID == plugin.ID && x.Metadata.Version.CompareTo(plugin.Version) < 0)) From 99405395ec418043fd76d73acf5838a8767c7de0 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sat, 20 Nov 2021 18:47:10 +1100 Subject: [PATCH 05/16] add plugin installation notifications --- .../Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml | 4 +++- .../Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index c36a1dcaac2..ba08dc3c56b 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -10,6 +10,8 @@ {0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart. Plugin Install Plugin Uninstall + Plugin installation in progress... Please wait + Plugin successfully installed. Restarting Flow, please wait... Install failed: unable to find the plugin.json metadata file from the new plugin Error installing plugin Error occured while trying to install {0} @@ -36,6 +38,6 @@ Suggest an enhancement or submit an issue Suggest an enhancement or submit an issue to the plugin developer Go to Flow's plugins repository - Visit the PluginsManifest repository to see comunity-made plugin submissions + Visit the PluginsManifest repository to see community-made plugin submissions \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 0ebbc2fdbee..419cae00fe3 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -47,7 +47,6 @@ internal PluginsManager(PluginInitContext context, Settings settings) private Task _downloadManifestTask = Task.CompletedTask; - internal Task UpdateManifestAsync() { if (_downloadManifestTask.Status == TaskStatus.Running) @@ -150,7 +149,11 @@ internal async Task InstallOrUpdate(UserPlugin plugin) Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), Context.API.GetTranslation("plugin_pluginsmanager_download_success")); + Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_title"), + Context.API.GetTranslation("plugin_pluginsmanager_install_in_progress")); + Install(plugin, filePath); + } catch (Exception e) { @@ -163,6 +166,9 @@ internal async Task InstallOrUpdate(UserPlugin plugin) return; } + Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_title"), + Context.API.GetTranslation("plugin_pluginsmanager_install_success_restart")); + Context.API.RestartApp(); } From 73c1031e0f950c4c2c743560aa77e49ae12023c6 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sat, 20 Nov 2021 20:01:57 +1100 Subject: [PATCH 06/16] append new guid as zip and file name, update error messaging --- .../Languages/en.xaml | 4 +-- .../PluginsManager.cs | 25 +++++++++++++------ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index ba08dc3c56b..0c0e8ea336f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -10,9 +10,9 @@ {0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart. Plugin Install Plugin Uninstall - Plugin installation in progress... Please wait + Plugin installation in progress. Please wait... Plugin successfully installed. Restarting Flow, please wait... - Install failed: unable to find the plugin.json metadata file from the new plugin + Unable to find the plugin.json metadata file from the extracted zip file. Error installing plugin Error occured while trying to install {0} No update available diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 419cae00fe3..546b31111ca 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -103,7 +103,7 @@ internal List GetDefaultHotKeys() internal async Task InstallOrUpdate(UserPlugin plugin) { - if (PluginExists(plugin.ID) || Directory.Exists(Path.Combine(DataLocation.PluginsDirectory, plugin.Name))) + if (PluginExists(plugin.ID)) { if (Context.API.GetAllPlugins() .Any(x => x.Metadata.ID == plugin.ID && x.Metadata.Version.CompareTo(plugin.Version) < 0)) @@ -137,7 +137,12 @@ internal async Task InstallOrUpdate(UserPlugin plugin) MessageBoxButton.YesNo) == MessageBoxResult.No) return; - var filePath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}-{plugin.Version}.zip"); + // at minimum should provide a name, but handle plugin that is not downloaded from plugins manifest and is a url download + var downloadFilename = string.IsNullOrEmpty(plugin.Version) + ? $"{plugin.Name}-{Guid.NewGuid()}.zip" + : $"{plugin.Name}-{plugin.Version}.zip"; + + var filePath = Path.Combine(DataLocation.PluginsDirectory, downloadFilename); try { @@ -153,11 +158,10 @@ internal async Task InstallOrUpdate(UserPlugin plugin) Context.API.GetTranslation("plugin_pluginsmanager_install_in_progress")); Install(plugin, filePath); - } catch (Exception e) { - Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), + Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), plugin.Name)); @@ -316,6 +320,7 @@ internal List InstallFromWeb(string url) { ID = "", Name = fileName.Split(".").First(), + Version = string.Empty, Author = "N/A", UrlDownload = url }; @@ -411,11 +416,15 @@ private void Install(UserPlugin plugin, string downloadedFilePath) if (string.IsNullOrEmpty(metadataJsonFilePath) || string.IsNullOrEmpty(pluginFolderPath)) { - MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile")); - return; + MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile"), + Context.API.GetTranslation("plugin_pluginsmanager_install_error_title")); + + throw new FileNotFoundException ( + string.Format("Unable to find plugin.json from the extracted zip file, or this path {0} does not exist", pluginFolderPath)); } - var directory = String.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}" : $"{plugin.Name}-{plugin.Version}"; - string newPluginPath = Path.Combine(DataLocation.PluginsDirectory, directory); + + var directory = string.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}-{Guid.NewGuid()}" : $"{plugin.Name}-{plugin.Version}"; + var newPluginPath = Path.Combine(DataLocation.PluginsDirectory, directory); FilesFolders.CopyAll(pluginFolderPath, newPluginPath); From 4eeaaec3c7f93356477ce3736b31e5f0d87590d3 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sat, 20 Nov 2021 21:26:56 +1100 Subject: [PATCH 07/16] fix naming when installed from url source --- .../Languages/en.xaml | 2 ++ .../PluginsManager.cs | 35 +++++++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index 0c0e8ea336f..fc4ff95ab06 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -6,6 +6,7 @@ Downloading plugin Please wait... Successfully downloaded + Error: Unable to download the plugin {0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart. {0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart. Plugin Install @@ -29,6 +30,7 @@ Plugins Manager Management of installing, uninstalling or updating Flow Launcher plugins + Unknown Author Open website diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 546b31111ca..f13e8d8ac60 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -17,6 +18,8 @@ namespace Flow.Launcher.Plugin.PluginsManager { internal class PluginsManager { + const string zip = "zip"; + private PluginInitContext Context { get; set; } private Settings Settings { get; set; } @@ -161,9 +164,18 @@ internal async Task InstallOrUpdate(UserPlugin plugin) } catch (Exception e) { - Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), + if (e is HttpRequestException) + { + MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_download_error"), + Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin")); + + } + else + { + Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), plugin.Name)); + } Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "InstallOrUpdate"); @@ -314,19 +326,21 @@ internal List Search(IEnumerable results, string searchName) internal List InstallFromWeb(string url) { - var fileName = url.Split("/").Last(); - var filePath = Path.Combine(DataLocation.PluginsDirectory, fileName); + var filename = url.Split("/").Last(); + var name = filename.Split(string.Format(".{0}", zip)).First(); + var plugin = new UserPlugin { ID = "", - Name = fileName.Split(".").First(), + Name = name, Version = string.Empty, - Author = "N/A", + Author = Context.API.GetTranslation("plugin_pluginsmanager_unknown_author"), UrlDownload = url }; + var result = new Result { - Title = fileName, + Title = filename, SubTitle = $"Download and Install from URL", IcoPath = icoPath, Action = e => @@ -342,6 +356,7 @@ internal List InstallFromWeb(string url) return ShouldHideWindow; } }; + return new List { result }; } @@ -356,6 +371,10 @@ internal async ValueTask> RequestInstallOrUpdate(string searchName, var searchNameWithoutKeyword = searchName.Replace(Settings.HotKeyInstall, string.Empty).Trim(); + if (Uri.IsWellFormedUriString(searchNameWithoutKeyword, UriKind.Absolute) + && searchNameWithoutKeyword.Split('.').Last() == zip) + return InstallFromWeb(searchNameWithoutKeyword); + var results = PluginsManifest .UserPlugins @@ -380,10 +399,6 @@ internal async ValueTask> RequestInstallOrUpdate(string searchName, ContextData = x }); - if (Uri.IsWellFormedUriString(searchNameWithoutKeyword, UriKind.Absolute)) - { - return InstallFromWeb(searchNameWithoutKeyword); - } return Search(results, searchNameWithoutKeyword); } From a796ac4c613271f4cb5024b6c84a5832df30f839 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 21 Nov 2021 00:06:53 +1100 Subject: [PATCH 08/16] add capability to only load unique plugins with the highest version --- Flow.Launcher.Core/Plugin/PluginConfig.cs | 54 +++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginConfig.cs b/Flow.Launcher.Core/Plugin/PluginConfig.cs index ea2119e60bc..4af344267dd 100644 --- a/Flow.Launcher.Core/Plugin/PluginConfig.cs +++ b/Flow.Launcher.Core/Plugin/PluginConfig.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.IO; @@ -45,8 +45,56 @@ public static List Parse(string[] pluginDirectories) } } } - - return allPluginMetadata; + + (List uniqueList, List duplicateList) = GetUniqueLatestPluginMetadata(allPluginMetadata); + + duplicateList + .ForEach( + x => Log.Warn("PluginConfig", + string.Format("Duplicate plugin name: {0}, id: {1}, version: {2} " + + "not loaded due to version not the highest of the duplicates", + x.Name, x.ID, x.Version), + "GetUniqueLatestPluginMetadata")); + + return uniqueList; + } + + private static (List, List) GetUniqueLatestPluginMetadata(List allPluginMetadata) + { + var duplicate_list = new List(); + var unique_list = new List(); + + var duplicateGroups = allPluginMetadata.GroupBy(x => x.ID).Where(g => g.Count() > 1).Select(y => y).ToList(); + + foreach (var metadata in allPluginMetadata) + { + var duplicatesExist = false; + foreach (var group in duplicateGroups) + { + if (metadata.ID == group.Key) + { + duplicatesExist = true; + + // If metadata's version greater than each duplicate's version, CompareTo > 0 + var count = group.Where(x => metadata.Version.CompareTo(x.Version) > 0).Count(); + + // Only add if the meatadata's version is the highest of all duplicates in the group + if (count == group.Count() - 1) + { + unique_list.Add(metadata); + } + else + { + duplicate_list.Add(metadata); + } + } + } + + if (!duplicatesExist) + unique_list.Add(metadata); + } + + return (unique_list, duplicate_list); } private static PluginMetadata GetPluginMetadata(string pluginDirectory) From ebf9ef1d8026d7ce1af84300ef42b0ac3698340e Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 21 Nov 2021 13:31:43 +1100 Subject: [PATCH 09/16] add check downloaded plugin zip has same or lesser version --- .../Languages/en.xaml | 1 + .../PluginsManager.cs | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index fc4ff95ab06..89ed9acf33a 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -14,6 +14,7 @@ Plugin installation in progress. Please wait... Plugin successfully installed. Restarting Flow, please wait... Unable to find the plugin.json metadata file from the extracted zip file. + Error: A plugin which has the same or greater version with {0} already exists. Error installing plugin Error occured while trying to install {0} No update available diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index f13e8d8ac60..adc4beb6c4e 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -10,6 +10,7 @@ using System.IO; using System.Linq; using System.Net.Http; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -438,6 +439,17 @@ private void Install(UserPlugin plugin, string downloadedFilePath) string.Format("Unable to find plugin.json from the extracted zip file, or this path {0} does not exist", pluginFolderPath)); } + if (SameOrLesserPluginVersionExists(metadataJsonFilePath)) + { + MessageBox.Show(string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_duplicate"), plugin.Name), + Context.API.GetTranslation("plugin_pluginsmanager_install_error_title")); + + throw new InvalidOperationException( + string.Format("A plugin with the same ID and version already exists, " + + "or the version is greater than this downloaded plugin {0}", + plugin.Name)); + } + var directory = string.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}-{Guid.NewGuid()}" : $"{plugin.Name}-{plugin.Version}"; var newPluginPath = Path.Combine(DataLocation.PluginsDirectory, directory); @@ -532,5 +544,14 @@ private List AutoCompleteReturnAllResults(string search, string hotkey, return new List(); } + + private bool SameOrLesserPluginVersionExists(string metadataPath) + { + var newMetadata = JsonSerializer.Deserialize(File.ReadAllText(metadataPath)); + return Context.API.GetAllPlugins() + .Any(x => x.Metadata.ID == newMetadata.ID + && (x.Metadata.Version == newMetadata.Version) + || newMetadata.Version.CompareTo(x.Metadata.Version) < 0); + } } } From a07252cc04af0dd3201d0866fd433ef00db1ec53 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 21 Nov 2021 16:09:49 +1100 Subject: [PATCH 10/16] add ability to switch off warning when unknown source fixed search terms to show with out to lower --- .../Languages/en.xaml | 9 +++- .../Main.cs | 12 ++++-- .../PluginsManager.cs | 41 +++++++++++++------ .../Settings.cs | 3 ++ .../ViewModels/SettingsViewModel.cs | 6 +++ .../Views/PluginsManagerSettings.xaml | 14 +++++-- .../Views/PluginsManagerSettings.xaml.cs | 2 +- 7 files changed, 64 insertions(+), 23 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index 89ed9acf33a..a30b8e966c1 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -10,6 +10,7 @@ {0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart. {0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart. Plugin Install + Download and install {0} Plugin Uninstall Plugin installation in progress. Please wait... Plugin successfully installed. Restarting Flow, please wait... @@ -25,7 +26,9 @@ 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. - + 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) + @@ -42,5 +45,7 @@ Suggest an enhancement or submit an issue to the plugin developer Go to Flow's plugins repository Visit the PluginsManifest repository to see community-made plugin submissions - + + + Install from unknown source warning \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 89a8e0ff5a1..f445826fa8c 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -55,7 +55,7 @@ public List LoadContextMenus(Result selectedResult) public async Task> QueryAsync(Query query, CancellationToken token) { - var search = query.Search.ToLower(); + var search = query.Search; if (string.IsNullOrWhiteSpace(search)) return pluginManager.GetDefaultHotKeys(); @@ -70,9 +70,13 @@ public async Task> QueryAsync(Query query, CancellationToken token) return search switch { - var s when s.StartsWith(Settings.HotKeyInstall) => await pluginManager.RequestInstallOrUpdate(s, token), - var s when s.StartsWith(Settings.HotkeyUninstall) => pluginManager.RequestUninstall(s), - var s when s.StartsWith(Settings.HotkeyUpdate) => await pluginManager.RequestUpdate(s, token), + //search could be url, no need ToLower() when passed in + var s when s.StartsWith(Settings.HotKeyInstall, StringComparison.OrdinalIgnoreCase) + => await pluginManager.RequestInstallOrUpdate(search, token), + var s when s.StartsWith(Settings.HotkeyUninstall, StringComparison.OrdinalIgnoreCase) + => pluginManager.RequestUninstall(search), + var s when s.StartsWith(Settings.HotkeyUpdate, StringComparison.OrdinalIgnoreCase) + => await pluginManager.RequestUpdate(search, token), _ => pluginManager.GetDefaultHotKeys().Where(hotkey => { hotkey.Score = StringMatcher.FuzzySearch(search, hotkey.Title).Score; diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index adc4beb6c4e..f37dd86ea7b 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -166,17 +166,12 @@ internal async Task InstallOrUpdate(UserPlugin plugin) catch (Exception e) { if (e is HttpRequestException) - { MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_download_error"), Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin")); - } - else - { - Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), + Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), plugin.Name)); - } Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "InstallOrUpdate"); @@ -206,7 +201,7 @@ internal async ValueTask> RequestUpdate(string search, Cancellation if (autocompletedResults.Any()) return autocompletedResults; - var uninstallSearch = search.Replace(Settings.HotkeyUpdate, string.Empty).TrimStart(); + var uninstallSearch = search.Replace(Settings.HotkeyUpdate, string.Empty, StringComparison.OrdinalIgnoreCase).TrimStart(); var resultsForUpdate = from existingPlugin in Context.API.GetAllPlugins() @@ -341,26 +336,46 @@ internal List InstallFromWeb(string url) var result = new Result { - Title = filename, - SubTitle = $"Download and Install from URL", + Title = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_from_web"), filename), + SubTitle = plugin.UrlDownload, IcoPath = icoPath, Action = e => { if (e.SpecialKeyState.CtrlPressed) { - SearchWeb.NewTabInBrowser(url); + SearchWeb.NewTabInBrowser(plugin.UrlDownload); return ShouldHideWindow; } + if (Settings.WarnFromUnknownSource) + { + if (!InstallSourceKnown(plugin.UrlDownload) + && 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"), + MessageBoxButton.YesNo) == MessageBoxResult.No) + return false; + } + Application.Current.MainWindow.Hide(); _ = InstallOrUpdate(plugin); + return ShouldHideWindow; } }; return new List { result }; } - + + private bool InstallSourceKnown(string url) + { + var author = url.Split('/')[3]; + var acceptedSource = "https://github.com"; + var contructedUrlPart = string.Format("{0}/{1}/", acceptedSource, author); + + return url.StartsWith(acceptedSource) && Context.API.GetAllPlugins().Any(x => x.Metadata.Website.StartsWith(contructedUrlPart)); + } + internal async ValueTask> RequestInstallOrUpdate(string searchName, CancellationToken token) { if (!PluginsManifest.UserPlugins.Any()) @@ -370,7 +385,7 @@ internal async ValueTask> RequestInstallOrUpdate(string searchName, token.ThrowIfCancellationRequested(); - var searchNameWithoutKeyword = searchName.Replace(Settings.HotKeyInstall, string.Empty).Trim(); + var searchNameWithoutKeyword = searchName.Replace(Settings.HotKeyInstall, string.Empty, StringComparison.OrdinalIgnoreCase).Trim(); if (Uri.IsWellFormedUriString(searchNameWithoutKeyword, UriKind.Absolute) && searchNameWithoutKeyword.Split('.').Last() == zip) @@ -468,7 +483,7 @@ internal List RequestUninstall(string search) if (autocompletedResults.Any()) return autocompletedResults; - var uninstallSearch = search.Replace(Settings.HotkeyUninstall, string.Empty).TrimStart(); + var uninstallSearch = search.Replace(Settings.HotkeyUninstall, string.Empty, StringComparison.OrdinalIgnoreCase).TrimStart(); var results = Context.API .GetAllPlugins() diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs index 9c5b0d29f6b..a951010c0b1 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs @@ -7,8 +7,11 @@ namespace Flow.Launcher.Plugin.PluginsManager internal class Settings { internal string HotKeyInstall { get; set; } = "install"; + internal string HotkeyUninstall { get; set; } = "uninstall"; internal string HotkeyUpdate { get; set; } = "update"; + + public bool WarnFromUnknownSource { get; set; } = true; } } diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/ViewModels/SettingsViewModel.cs index 8ca4c614a45..11303f47256 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/ViewModels/SettingsViewModel.cs @@ -14,5 +14,11 @@ public SettingsViewModel(PluginInitContext context, Settings settings) Context = context; Settings = settings; } + + public bool WarnFromUnknownSource + { + get => Settings.WarnFromUnknownSource; + set => Settings.WarnFromUnknownSource = value; + } } } diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Views/PluginsManagerSettings.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Views/PluginsManagerSettings.xaml index 89d27f6ffea..d758030663d 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Views/PluginsManagerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Views/PluginsManagerSettings.xaml @@ -3,10 +3,18 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:local="clr-namespace:Flow.Launcher.Plugin.PluginsManager.ViewModels" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> - - + + + + + + + + diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Views/PluginsManagerSettings.xaml.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Views/PluginsManagerSettings.xaml.cs index 703682e074f..26668cc0529 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Views/PluginsManagerSettings.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Views/PluginsManagerSettings.xaml.cs @@ -16,7 +16,7 @@ internal PluginsManagerSettings(SettingsViewModel viewModel) this.viewModel = viewModel; - //RefreshView(); + this.DataContext = viewModel; } } } From c7e77e3912a6b6f6c363e2a42384b55c5299770e Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 21 Nov 2021 16:54:30 +1100 Subject: [PATCH 11/16] add tests for loading unique metadata method --- Flow.Launcher.Core/Plugin/PluginConfig.cs | 2 +- Flow.Launcher.Test/PluginLoadTest.cs | 91 ++++++++++++++++++++ Flow.Launcher.Test/Plugins/PluginInitTest.cs | 17 ---- 3 files changed, 92 insertions(+), 18 deletions(-) create mode 100644 Flow.Launcher.Test/PluginLoadTest.cs delete mode 100644 Flow.Launcher.Test/Plugins/PluginInitTest.cs diff --git a/Flow.Launcher.Core/Plugin/PluginConfig.cs b/Flow.Launcher.Core/Plugin/PluginConfig.cs index 4af344267dd..dd6517a7fd1 100644 --- a/Flow.Launcher.Core/Plugin/PluginConfig.cs +++ b/Flow.Launcher.Core/Plugin/PluginConfig.cs @@ -59,7 +59,7 @@ public static List Parse(string[] pluginDirectories) return uniqueList; } - private static (List, List) GetUniqueLatestPluginMetadata(List allPluginMetadata) + internal static (List, List) GetUniqueLatestPluginMetadata(List allPluginMetadata) { var duplicate_list = new List(); var unique_list = new List(); diff --git a/Flow.Launcher.Test/PluginLoadTest.cs b/Flow.Launcher.Test/PluginLoadTest.cs new file mode 100644 index 00000000000..28a0ffcb458 --- /dev/null +++ b/Flow.Launcher.Test/PluginLoadTest.cs @@ -0,0 +1,91 @@ +using NUnit.Framework; +using Flow.Launcher.Core.Plugin; +using Flow.Launcher.Plugin; +using System.Collections.Generic; +using System.Linq; + +namespace Flow.Launcher.Test +{ + [TestFixture] + class PluginLoadTest + { + [Test] + public void GivenDuplicatePluginMetadatasWhenLoadedThenShouldReturnOnlyUniqueList() + { + // Given + var duplicateList = new List + { + new PluginMetadata + { + ID = "CEA0TYUC6D3B4085823D60DC76F28855", + Version = "1.0.0" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B4085823D60DC76F28855", + Version = "1.0.1" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B4085823D60DC76F28855", + Version = "1.0.2" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B4085823D60DC76F28855", + Version = "1.0.0" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B4085823D60DC76F28855", + Version = "1.0.0" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B7855823D60DC76F28855", + Version = "1.0.0" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B7855823D60DC76F28855", + Version = "1.0.0" + } + }; + + // When + (var unique, var duplicates) = PluginConfig.GetUniqueLatestPluginMetadata(duplicateList); + + // Then + Assert.True(unique.FirstOrDefault().ID == "CEA0TYUC6D3B4085823D60DC76F28855" && unique.FirstOrDefault().Version == "1.0.2"); + Assert.True(unique.Count() == 1); + + Assert.True(duplicates.Where(x => x.Version != "1.0.2" && x.ID == "CEA0TYUC6D3B4085823D60DC76F28855").Count() == 6); + } + + [Test] + public void GivenDuplicatePluginMetadatasWithNoUniquePluginWhenLoadedThenShouldReturnEmptyList() + { + // Given + var duplicateList = new List + { + new PluginMetadata + { + ID = "CEA0TYUC6D3B7855823D60DC76F28855", + Version = "1.0.0" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B7855823D60DC76F28855", + Version = "1.0.0" + } + }; + + // When + (var unique, var duplicates) = PluginConfig.GetUniqueLatestPluginMetadata(duplicateList); + + // Then + Assert.True(unique.Count() == 0); + Assert.True(duplicates.Count() == 2); + } + } +} diff --git a/Flow.Launcher.Test/Plugins/PluginInitTest.cs b/Flow.Launcher.Test/Plugins/PluginInitTest.cs deleted file mode 100644 index 299a837ee0e..00000000000 --- a/Flow.Launcher.Test/Plugins/PluginInitTest.cs +++ /dev/null @@ -1,17 +0,0 @@ -using NUnit.Framework; -using Flow.Launcher.Core.Plugin; -using Flow.Launcher.Infrastructure.Exception; - -namespace Flow.Launcher.Test.Plugins -{ - - [TestFixture] - public class PluginInitTest - { - [Test] - public void PublicAPIIsNullTest() - { - //Assert.Throws(typeof(Flow.LauncherFatalException), () => PluginManager.Initialize(null)); - } - } -} From 7868d62974aa4bd39479b528507afe2835310bef Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 21 Nov 2021 17:16:46 +1100 Subject: [PATCH 12/16] update test --- Flow.Launcher.Test/PluginLoadTest.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Test/PluginLoadTest.cs b/Flow.Launcher.Test/PluginLoadTest.cs index 28a0ffcb458..d6ba48f1905 100644 --- a/Flow.Launcher.Test/PluginLoadTest.cs +++ b/Flow.Launcher.Test/PluginLoadTest.cs @@ -42,12 +42,12 @@ public void GivenDuplicatePluginMetadatasWhenLoadedThenShouldReturnOnlyUniqueLis }, new PluginMetadata { - ID = "CEA0TYUC6D3B7855823D60DC76F28855", + ID = "ABC0TYUC6D3B7855823D60DC76F28855", Version = "1.0.0" }, new PluginMetadata { - ID = "CEA0TYUC6D3B7855823D60DC76F28855", + ID = "ABC0TYUC6D3B7855823D60DC76F28855", Version = "1.0.0" } }; @@ -59,7 +59,8 @@ public void GivenDuplicatePluginMetadatasWhenLoadedThenShouldReturnOnlyUniqueLis Assert.True(unique.FirstOrDefault().ID == "CEA0TYUC6D3B4085823D60DC76F28855" && unique.FirstOrDefault().Version == "1.0.2"); Assert.True(unique.Count() == 1); - Assert.True(duplicates.Where(x => x.Version != "1.0.2" && x.ID == "CEA0TYUC6D3B4085823D60DC76F28855").Count() == 6); + Assert.False(duplicates.Any(x => x.Version == "1.0.2" && x.ID == "CEA0TYUC6D3B4085823D60DC76F28855")); + Assert.True(duplicates.Count() == 6); } [Test] From 48c0f21a24819912a52fcb9f3d5e5b2bf02ef518 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 22 Nov 2021 19:43:14 +1100 Subject: [PATCH 13/16] only msg plugin download & install succes/failure --- .../Languages/en.xaml | 2 -- .../Languages/sk.xaml | 1 - .../Languages/zh-cn.xaml | 1 - .../PluginsManager.cs | 10 ---------- 4 files changed, 14 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index a30b8e966c1..a15c50ccfea 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -4,7 +4,6 @@ Downloading plugin - Please wait... Successfully downloaded Error: Unable to download the plugin {0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart. @@ -12,7 +11,6 @@ Plugin Install Download and install {0} Plugin Uninstall - Plugin installation in progress. Please wait... Plugin successfully installed. Restarting Flow, please wait... Unable to find the plugin.json metadata file from the extracted zip file. Error: A plugin which has the same or greater version with {0} already exists. diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml index 52cd784ee59..4f37dfe8364 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml @@ -4,7 +4,6 @@ Sťahovanie pluginu - Čakajte, prosím… Úspešne stiahnuté {0} od {1} {2}{3}Chcete odinštalovať tento plugin? Po odinštalovaní sa Flow automaticky reštartuje. {0} by {1} {2}{3}Chcete nainštalovať tento plugin? Po nainštalovaní sa Flow automaticky reštartuje. diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml index 6a060a7fe55..d74ab008ff9 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml @@ -4,7 +4,6 @@ 下载插件 - 请稍等... 下载完成 {0} by {1} {2}{3} 您要卸载此插件吗? 卸载后,Flow Launcher 将自动重启。 {0} by {1} {2}{3} 您要安装此插件吗? 安装后,Flow Launcher 将自动重启 diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index f37dd86ea7b..c0278038325 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -150,17 +150,11 @@ internal async Task InstallOrUpdate(UserPlugin plugin) try { - Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), - Context.API.GetTranslation("plugin_pluginsmanager_please_wait")); - await Http.DownloadAsync(plugin.UrlDownload, filePath).ConfigureAwait(false); Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), Context.API.GetTranslation("plugin_pluginsmanager_download_success")); - Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_title"), - Context.API.GetTranslation("plugin_pluginsmanager_install_in_progress")); - Install(plugin, filePath); } catch (Exception e) @@ -257,10 +251,6 @@ where existingPlugin.Metadata.Version.CompareTo(pluginFromManifest.Version) < Task.Run(async delegate { - Context.API.ShowMsg( - Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), - Context.API.GetTranslation("plugin_pluginsmanager_please_wait")); - await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath) .ConfigureAwait(false); From 76efdfcff0cc96a2d1179012c790aa67749f19cb Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 22 Nov 2021 19:45:21 +1100 Subject: [PATCH 14/16] version bump PluginsManager --- Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json index 59202510300..bf1ae5d8e55 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json @@ -6,7 +6,7 @@ "Name": "Plugins Manager", "Description": "Management of installing, uninstalling or updating Flow Launcher plugins", "Author": "Jeremy Wu", - "Version": "1.9.0", + "Version": "1.10.0", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll", From 2edc34589291f58302b755ab38151c855c9c7fd3 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 24 Nov 2021 02:06:39 -0500 Subject: [PATCH 15/16] Fix or condition --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index c0278038325..60059c7e99e 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -555,8 +555,8 @@ private bool SameOrLesserPluginVersionExists(string metadataPath) var newMetadata = JsonSerializer.Deserialize(File.ReadAllText(metadataPath)); return Context.API.GetAllPlugins() .Any(x => x.Metadata.ID == newMetadata.ID - && (x.Metadata.Version == newMetadata.Version) - || newMetadata.Version.CompareTo(x.Metadata.Version) < 0); + && (x.Metadata.Version == newMetadata.Version + || newMetadata.Version.CompareTo(x.Metadata.Version) < 0)); } } } From ea179e54552f0d1c0881f99aa10522c47bf67b18 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 29 Nov 2021 06:06:08 +1100 Subject: [PATCH 16/16] shorten version compare logic --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 60059c7e99e..8db54de3521 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -555,8 +555,7 @@ private bool SameOrLesserPluginVersionExists(string metadataPath) var newMetadata = JsonSerializer.Deserialize(File.ReadAllText(metadataPath)); return Context.API.GetAllPlugins() .Any(x => x.Metadata.ID == newMetadata.ID - && (x.Metadata.Version == newMetadata.Version - || newMetadata.Version.CompareTo(x.Metadata.Version) < 0)); + && newMetadata.Version.CompareTo(x.Metadata.Version) <= 0); } } }