From f12ea653d29fe2152293460f72483ae397551d74 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 17 Dec 2020 18:54:30 +1100 Subject: [PATCH 1/7] move autocomplete to method --- .../PluginsManager.cs | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index c141916aa..ea94ab6ef 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -42,7 +42,7 @@ namespace Flow.Launcher.Plugin.PluginsManager if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_install_title"), MessageBoxButton.YesNo) == MessageBoxResult.No) return; - var filePath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}{plugin.ID}.zip"); + var filePath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}-{plugin.Version}.zip"); try { @@ -65,9 +65,9 @@ namespace Flow.Launcher.Plugin.PluginsManager Application.Current.Dispatcher.Invoke(() => Install(plugin, filePath)); } - internal void Update() + internal void Update(string search) { - throw new NotImplementedException(); + } internal bool PluginExists(string id) @@ -75,12 +75,6 @@ namespace Flow.Launcher.Plugin.PluginsManager return Context.API.GetAllPlugins().Any(x => x.Metadata.ID == id); } - internal void PluginsManifestSiteOpen() - { - //Open from context menu https://git.vcmq.workers.dev/Flow-Launcher/Flow.Launcher.PluginsManifest - throw new NotImplementedException(); - } - internal List Search(List results, string searchName) { if (string.IsNullOrEmpty(searchName)) @@ -162,29 +156,13 @@ namespace Flow.Launcher.Plugin.PluginsManager internal List RequestUninstall(string search) { - if (!string.IsNullOrEmpty(search) - && Settings.UninstallHotkey.StartsWith(search) - && (Settings.UninstallHotkey != search || !search.StartsWith(Settings.UninstallHotkey))) - { - return - new List - { - new Result - { - Title = "Uninstall", - IcoPath = icoPath, - SubTitle = "Select a plugin to uninstall", - Action = e => - { - Context - .API - .ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.UninstallHotkey} "); + var autocompletedResults = AutoCompleteReturnAllResults(search, + Settings.UninstallHotkey, + "Uninstall", + "Select a plugin to uninstall"); - return false; - } - } - }; - } + if (autocompletedResults.Any()) + return autocompletedResults; var uninstallSearch = search.Replace(Settings.UninstallHotkey, string.Empty).TrimStart(); @@ -223,5 +201,34 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.RestartApp(); } } + + private List AutoCompleteReturnAllResults(string search, string hotkey, string title, string subtitle) + { + if (!string.IsNullOrEmpty(search) + && hotkey.StartsWith(search) + && (hotkey != search || !search.StartsWith(hotkey))) + { + return + new List + { + new Result + { + Title = title, + IcoPath = icoPath, + SubTitle = subtitle, + Action = e => + { + Context + .API + .ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {hotkey} "); + + return false; + } + } + }; + } + + return new List(); + } } } From df454778ec2d6fedad6e3b57d1e39a5b5acc8879 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 17 Dec 2020 19:00:27 +1100 Subject: [PATCH 2/7] update plugin containing folder name from id to version --- 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 ea94ab6ef..1b13dabf8 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -147,7 +147,7 @@ namespace Flow.Launcher.Plugin.PluginsManager return; } - string newPluginPath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}{plugin.ID}"); + string newPluginPath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}-{plugin.Version}"); Directory.Move(pluginFolderPath, newPluginPath); From 7e8c49502e38e9473affba6f57a793a6e89e21a5 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 17 Dec 2020 20:37:01 +1100 Subject: [PATCH 3/7] add plugin update call --- .../Languages/en.xaml | 5 + .../Main.cs | 8 +- .../Models/UserPlugin.cs | 5 +- .../PluginsManager.cs | 110 ++++++++++++++---- .../Settings.cs | 4 +- 5 files changed, 105 insertions(+), 27 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index 7f8557c28..f69f23f6b 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -11,6 +11,11 @@ Plugin Install Plugin Uninstall Install failed: unable to find the plugin.json metadata file from the new plugin + No update available + All plugins are up to date + {0} by {1} {2}{3}Would you like to update this plugin? After the update Flow will automatically restart. + Plugin Update + diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 58ec5005f..43f92e7b9 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -42,9 +42,13 @@ namespace Flow.Launcher.Plugin.PluginsManager var pluginManager = new PluginsManager(Context, Settings); if (!string.IsNullOrEmpty(search) - && ($"{Settings.UninstallHotkey} ".StartsWith(search) || search.StartsWith($"{Settings.UninstallHotkey} "))) + && ($"{Settings.HotkeyUninstall} ".StartsWith(search) || search.StartsWith($"{Settings.HotkeyUninstall} "))) return pluginManager.RequestUninstall(search); - + + if (!string.IsNullOrEmpty(search) + && ($"{Settings.HotkeyUpdate} ".StartsWith(search) || search.StartsWith($"{Settings.HotkeyUpdate} "))) + return pluginManager.RequestUpdate(search); + return pluginManager.RequestInstallOrUpdate(search); } diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/UserPlugin.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/UserPlugin.cs index 3bc44e0f6..c1af3014b 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/UserPlugin.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/UserPlugin.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - + namespace Flow.Launcher.Plugin.PluginsManager.Models { public class UserPlugin diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 1b13dabf8..37051e4da 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -62,12 +62,82 @@ namespace Flow.Launcher.Plugin.PluginsManager Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "PluginDownload"); } - Application.Current.Dispatcher.Invoke(() => Install(plugin, filePath)); + Application.Current.Dispatcher.Invoke(() => { Install(plugin, filePath); Context.API.RestartApp(); }); } - internal void Update(string search) + internal List RequestUpdate(string search) { + var autocompletedResults = AutoCompleteReturnAllResults(search, + Settings.HotkeyUpdate, + "Update", + "Select a plugin to update"); + if (autocompletedResults.Any()) + return autocompletedResults; + + var uninstallSearch = search.Replace(Settings.HotkeyUpdate, string.Empty).TrimStart(); + + + var resultsForUpdate = + from existingPlugin in Context.API.GetAllPlugins() + join pluginFromManifest in pluginsManifest.UserPlugins + on existingPlugin.Metadata.ID equals pluginFromManifest.ID + where existingPlugin.Metadata.Version != pluginFromManifest.Version + select + new + { + pluginFromManifest.Name, + pluginFromManifest.Author, + CurrentVersion = existingPlugin.Metadata.Version, + NewVersion = pluginFromManifest.Version, + existingPlugin.Metadata.IcoPath, + PluginExistingMetadata = existingPlugin.Metadata, + PluginNewUserPlugin = pluginFromManifest + }; + + if (!resultsForUpdate.Any()) + return new List { + new Result + { + Title = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_title"), + SubTitle = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_subtitle"), + IcoPath = icoPath + }}; + + + var results = resultsForUpdate + .Select(x => + new Result + { + Title = $"{x.Name} by {x.Author}", + SubTitle = $"Update from version {x.CurrentVersion} to {x.NewVersion}", + IcoPath = x.IcoPath, + Action = e => + { + string message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_update_prompt"), + x.Name, x.Author, + Environment.NewLine, Environment.NewLine); + + if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_update_title"), + MessageBoxButton.YesNo) == MessageBoxResult.Yes) + { + Uninstall(x.PluginExistingMetadata); + + var downloadToFilePath = Path.Combine(DataLocation.PluginsDirectory, $"{x.Name}-{x.NewVersion}.zip"); + Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath); + Install(x.PluginNewUserPlugin, downloadToFilePath); + + Context.API.RestartApp(); + + return true; + } + + return false; + } + }) + .ToList(); + + return Search(results, uninstallSearch); } internal bool PluginExists(string id) @@ -150,21 +220,19 @@ namespace Flow.Launcher.Plugin.PluginsManager string newPluginPath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}-{plugin.Version}"); Directory.Move(pluginFolderPath, newPluginPath); - - Context.API.RestartApp(); } internal List RequestUninstall(string search) { var autocompletedResults = AutoCompleteReturnAllResults(search, - Settings.UninstallHotkey, + Settings.HotkeyUninstall, "Uninstall", "Select a plugin to uninstall"); if (autocompletedResults.Any()) return autocompletedResults; - var uninstallSearch = search.Replace(Settings.UninstallHotkey, string.Empty).TrimStart(); + var uninstallSearch = search.Replace(Settings.HotkeyUninstall, string.Empty).TrimStart(); var results= Context.API .GetAllPlugins() @@ -176,10 +244,21 @@ namespace Flow.Launcher.Plugin.PluginsManager IcoPath = x.Metadata.IcoPath, Action = e => { - Application.Current.MainWindow.Hide(); - Uninstall(x.Metadata); + string message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_prompt"), + x.Metadata.Name, x.Metadata.Author, + Environment.NewLine, Environment.NewLine); - return true; + if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_uninstall_title"), + MessageBoxButton.YesNo) == MessageBoxResult.Yes) + { + Application.Current.MainWindow.Hide(); + Uninstall(x.Metadata); + Context.API.RestartApp(); + + return true; + } + + return false; } }) .ToList(); @@ -189,17 +268,8 @@ namespace Flow.Launcher.Plugin.PluginsManager private void Uninstall(PluginMetadata plugin) { - string message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_prompt"), - plugin.Name, plugin.Author, - Environment.NewLine, Environment.NewLine); - - if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_uninstall_title"), - MessageBoxButton.YesNo) == MessageBoxResult.Yes) - { - using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, "NeedDelete.txt")); - - Context.API.RestartApp(); - } + // Marked for deletion. Will be deleted on next start up + using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, "NeedDelete.txt")); } private List AutoCompleteReturnAllResults(string search, string hotkey, string title, string subtitle) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs index 0c647e6ae..e2e8d22e5 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs @@ -6,6 +6,8 @@ namespace Flow.Launcher.Plugin.PluginsManager { internal class Settings { - internal string UninstallHotkey { get; set; } = "uninstall"; + internal string HotkeyUninstall { get; set; } = "uninstall"; + + internal string HotkeyUpdate { get; set; } = "update"; } } From ceab9b2ecd8d4da48ff30c8fc8587d6df8138207 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 17 Dec 2020 20:37:24 +1100 Subject: [PATCH 4/7] PluginsManager version bump --- 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 0353fffcc..e970e5a8e 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.1.0", + "Version": "1.3.0", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll", From cca53c2a7d34d6d99c6a6dcae1ec17c018e0419f Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 17 Dec 2020 21:07:47 +1100 Subject: [PATCH 5/7] add hide main window override --- .../PluginsManager.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 37051e4da..22682cae4 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -19,6 +19,21 @@ namespace Flow.Launcher.Plugin.PluginsManager private Settings Settings { get; set; } + private bool shouldHideWindow = true; + private bool ShouldHideWindow + { + set { shouldHideWindow = value; } + get + { + var setValue = shouldHideWindow; + // Default value for hide main window is true. Revert after get call. + // This ensures when set by another method to false, it is only used once. + shouldHideWindow = true; + + return setValue; + } + } + private readonly string icoPath = "Images\\pluginsmanager.png"; internal PluginsManager(PluginInitContext context, Settings settings) @@ -178,7 +193,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Application.Current.MainWindow.Hide(); InstallOrUpdate(x); - return true; + return ShouldHideWindow; } }) .ToList(); From c2ca29dcdae315ddcf6735fb4b74ed7557eaa761 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 17 Dec 2020 21:37:38 +1100 Subject: [PATCH 6/7] add go to update section if update exists when install --- .../Languages/en.xaml | 2 ++ .../PluginsManager.cs | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index f69f23f6b..a5be6c63c 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -15,6 +15,8 @@ All plugins are up to date {0} by {1} {2}{3}Would you like to update this plugin? After the update Flow will automatically restart. Plugin Update + This plugin has an update, would you like to see it? + This plugin is already installed diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 22682cae4..dad183227 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -46,7 +46,22 @@ namespace Flow.Launcher.Plugin.PluginsManager { if (PluginExists(plugin.ID)) { - Context.API.ShowMsg("Plugin already installed"); + if (Context.API.GetAllPlugins().Any(x => x.Metadata.ID == plugin.ID && x.Metadata.Version != plugin.Version)) + { + if (MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_update_exists"), + Context.API.GetTranslation("plugin_pluginsmanager_update_title"), + MessageBoxButton.YesNo) == MessageBoxResult.Yes) + Context + .API + .ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.HotkeyUpdate} {plugin.Name}"); + + Application.Current.MainWindow.Show(); + shouldHideWindow = false; + + return; + } + + Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_alreadyexists")); return; } From 5ab021f4449e19c5d935f96ec7f5cf835b5c2d9e Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sun, 20 Dec 2020 20:08:52 +1100 Subject: [PATCH 7/7] update per comment --- .../PluginsManager.cs | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index bd80b3dfd..90f3277fb 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -138,34 +138,33 @@ namespace Flow.Launcher.Plugin.PluginsManager var results = resultsForUpdate .Select(x => new Result + { + Title = $"{x.Name} by {x.Author}", + SubTitle = $"Update from version {x.CurrentVersion} to {x.NewVersion}", + IcoPath = x.IcoPath, + Action = e => { - Title = $"{x.Name} by {x.Author}", - SubTitle = $"Update from version {x.CurrentVersion} to {x.NewVersion}", - IcoPath = x.IcoPath, - Action = e => + string message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_update_prompt"), + x.Name, x.Author, + Environment.NewLine, Environment.NewLine); + + if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_update_title"), + MessageBoxButton.YesNo) == MessageBoxResult.Yes) { - string message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_update_prompt"), - x.Name, x.Author, - Environment.NewLine, Environment.NewLine); + Uninstall(x.PluginExistingMetadata); - if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_update_title"), - MessageBoxButton.YesNo) == MessageBoxResult.Yes) - { - Uninstall(x.PluginExistingMetadata); + var downloadToFilePath = Path.Combine(DataLocation.PluginsDirectory, $"{x.Name}-{x.NewVersion}.zip"); + Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath); + Install(x.PluginNewUserPlugin, downloadToFilePath); - var downloadToFilePath = Path.Combine(DataLocation.PluginsDirectory, $"{x.Name}-{x.NewVersion}.zip"); - Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath); - Install(x.PluginNewUserPlugin, downloadToFilePath); + Context.API.RestartApp(); - Context.API.RestartApp(); - - return true; - } - - return false; + return true; } - }) - .ToList(); + + return false; + } + }); return Search(results, uninstallSearch); } @@ -175,10 +174,10 @@ namespace Flow.Launcher.Plugin.PluginsManager return Context.API.GetAllPlugins().Any(x => x.Metadata.ID == id); } - internal List Search(List results, string searchName) + internal List Search(IEnumerable results, string searchName) { if (string.IsNullOrEmpty(searchName)) - return results; + return results.ToList(); return results .Where(x => @@ -211,8 +210,7 @@ namespace Flow.Launcher.Plugin.PluginsManager return ShouldHideWindow; }, ContextData = x - }) - .ToList(); + }); return Search(results, searchName); } @@ -265,7 +263,7 @@ namespace Flow.Launcher.Plugin.PluginsManager var uninstallSearch = search.Replace(Settings.HotkeyUninstall, string.Empty).TrimStart(); - var results= Context.API + var results = Context.API .GetAllPlugins() .Select(x => new Result @@ -291,8 +289,7 @@ namespace Flow.Launcher.Plugin.PluginsManager return false; } - }) - .ToList(); + }); return Search(results, uninstallSearch); }