From d41dd780ce631d1ef0aa61dd53a68204bb85fc72 Mon Sep 17 00:00:00 2001 From: Spencer Hedrick Date: Sat, 9 Oct 2021 02:36:38 -0700 Subject: [PATCH 01/31] add initial ShellRun support for JsonRPC --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 6 ++++++ Flow.Launcher/PublicAPIInstance.cs | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index d9cdf5581..3cadae176 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -29,6 +29,12 @@ namespace Flow.Launcher.Plugin /// void RestartApp(); + /// + /// Run a shell command or external program + /// + /// The command or program to run + void ShellRun(string cmd); + /// /// Save everything, all of Flow Launcher and plugins' data and settings /// diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 6f995671d..c528b8229 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -103,6 +103,16 @@ namespace Flow.Launcher }); } + public void ShellRun(string cmd) + { + System.Diagnostics.Process process = new(); + var startInfo = process.StartInfo; + startInfo.FileName = "cmd.exe"; + startInfo.Arguments = $"/C {cmd}"; + startInfo.CreateNoWindow = true; + process.Start(); + } + public void StartLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Visible; public void StopLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Collapsed; From ae7de8db0932ee71b0506cca74479dd371ccde3a Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 17 Nov 2021 21:00:36 +1100 Subject: [PATCH 02/31] refactor to use ShellCommand --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 2 ++ .../SharedCommands/ShellCommand.cs | 28 +++++++++++++++++-- Flow.Launcher/PublicAPIInstance.cs | 12 +++----- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 2 +- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 4 +-- 5 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 3cadae176..7d4741630 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -33,6 +33,8 @@ namespace Flow.Launcher.Plugin /// Run a shell command or external program /// /// The command or program to run + /// Thrown when unable to find the file specified in the command + /// Thrown when error occurs during the execution of the command void ShellRun(string cmd); /// diff --git a/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs b/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs index c5d43a3d9..a2eea19a7 100644 --- a/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs +++ b/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -60,17 +60,39 @@ namespace Flow.Launcher.Plugin.SharedCommands return sb.ToString(); } - public static ProcessStartInfo SetProcessStartInfo(this string fileName, string workingDirectory = "", string arguments = "", string verb = "") + public static ProcessStartInfo SetProcessStartInfo(this string fileName, string workingDirectory = "", string arguments = "", string verb = "", bool createNoWindow = false) { var info = new ProcessStartInfo { FileName = fileName, WorkingDirectory = workingDirectory, Arguments = arguments, - Verb = verb + Verb = verb, + CreateNoWindow = createNoWindow }; return info; } + + /// + /// Runs a windows command using the provided ProcessStartInfo + /// + /// Thrown when unable to find the file specified in the command + /// Thrown when error occurs during the execution of the command + public static void Execute(ProcessStartInfo info) + { + Execute(Process.Start, info); + } + + /// + /// Runs a windows command using the provided ProcessStartInfo using a custom execute command function + /// + /// allows you to pass in a custom command execution function + /// Thrown when unable to find the file specified in the command + /// Thrown when error occurs during the execution of the command + public static void Execute(Func startProcess, ProcessStartInfo info) + { + startProcess(info); + } } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index c528b8229..6ca14c215 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net; @@ -14,6 +14,7 @@ using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; using Flow.Launcher.Plugin.SharedModels; +using Flow.Launcher.Plugin.SharedCommands; using System.Threading; using System.IO; using Flow.Launcher.Infrastructure.Http; @@ -102,15 +103,10 @@ namespace Flow.Launcher SettingWindow sw = SingletonWindowOpener.Open(this, _settingsVM); }); } - public void ShellRun(string cmd) { - System.Diagnostics.Process process = new(); - var startInfo = process.StartInfo; - startInfo.FileName = "cmd.exe"; - startInfo.Arguments = $"/C {cmd}"; - startInfo.CreateNoWindow = true; - process.Start(); + var startInfo = ShellCommand.SetProcessStartInfo("cmd.exe", arguments: $"/C {cmd}", createNoWindow: true); + ShellCommand.Execute(startInfo); } public void StartLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Visible; diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 0a934ab32..c6b4999e1 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -251,7 +251,7 @@ namespace Flow.Launcher.Plugin.Shell { try { - startProcess(info); + ShellCommand.Execute(startProcess, info); } catch (FileNotFoundException e) { diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 282c8a25d..fcf2df4a5 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -190,8 +190,8 @@ namespace Flow.Launcher.Plugin.Sys var info = ShellCommand.SetProcessStartInfo("shutdown", arguments:"/h"); info.WindowStyle = ProcessWindowStyle.Hidden; info.UseShellExecute = true; - - Process.Start(info); + + ShellCommand.Execute(info); return true; } From 02d101a30b520c8d2ab2b26b6b347b72e6339c87 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 17 Nov 2021 21:04:00 +1100 Subject: [PATCH 03/31] fix formatting --- Flow.Launcher/PublicAPIInstance.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 1d0136c6f..360529ea9 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -106,6 +106,7 @@ namespace Flow.Launcher SettingWindow sw = SingletonWindowOpener.Open(this, _settingsVM); }); } + public void ShellRun(string cmd) { var startInfo = ShellCommand.SetProcessStartInfo("cmd.exe", arguments: $"/C {cmd}", createNoWindow: true); From 3e38a9035cca56eef9e23bda088bba4b56dfd9b6 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 17 Nov 2021 21:07:44 +1100 Subject: [PATCH 04/31] version bump plugins --- Plugins/Flow.Launcher.Plugin.Shell/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.Sys/plugin.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json index 6b20eeef9..b71dba2da 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json @@ -4,7 +4,7 @@ "Name": "Shell", "Description": "Provide executing commands from Flow Launcher", "Author": "qianlifeng", - "Version": "1.4.5", + "Version": "1.4.6", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Shell.dll", diff --git a/Plugins/Flow.Launcher.Plugin.Sys/plugin.json b/Plugins/Flow.Launcher.Plugin.Sys/plugin.json index 42e8058e5..1a8f008c3 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Sys/plugin.json @@ -4,7 +4,7 @@ "Name": "System Commands", "Description": "Provide System related commands. e.g. shutdown,lock, setting etc.", "Author": "qianlifeng", - "Version": "1.5.0", + "Version": "1.5.1", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Sys.dll", From ef56d91c2ff117fd19b0e2cc06b749d0b431632b Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 18 Nov 2021 05:56:51 +1100 Subject: [PATCH 05/31] add filename param to ShellRun command for running other shell types --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 2 +- Flow.Launcher/PublicAPIInstance.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index a5602ac13..0897de8a4 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -35,7 +35,7 @@ namespace Flow.Launcher.Plugin /// The command or program to run /// Thrown when unable to find the file specified in the command /// Thrown when error occurs during the execution of the command - void ShellRun(string cmd); + void ShellRun(string cmd, string filename = "cmd.exe"); /// /// Save everything, all of Flow Launcher and plugins' data and settings diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 360529ea9..eda173ee1 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -107,9 +107,9 @@ namespace Flow.Launcher }); } - public void ShellRun(string cmd) + public void ShellRun(string cmd, string filename = "cmd.exe") { - var startInfo = ShellCommand.SetProcessStartInfo("cmd.exe", arguments: $"/C {cmd}", createNoWindow: true); + var startInfo = ShellCommand.SetProcessStartInfo(filename, arguments: $"/C {cmd}", createNoWindow: true); ShellCommand.Execute(startInfo); } From 8cf93907e98e330d7e8e165bcc887888f2c98cb7 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 18 Nov 2021 05:59:37 +1100 Subject: [PATCH 06/31] update comment --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 0897de8a4..908284bb9 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -30,9 +30,10 @@ namespace Flow.Launcher.Plugin void RestartApp(); /// - /// Run a shell command or external program + /// Run a shell command /// /// The command or program to run + /// the shell type to run, e.g. powershell.exe /// Thrown when unable to find the file specified in the command /// Thrown when error occurs during the execution of the command void ShellRun(string cmd, string filename = "cmd.exe"); From a7ef5895b700cc4c6e60fac7780309bc12660b2b Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 18 Nov 2021 06:15:38 +1100 Subject: [PATCH 07/31] update StartInfo arguments if cmd shell type --- Flow.Launcher/PublicAPIInstance.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index eda173ee1..d0dc54874 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -109,7 +109,9 @@ namespace Flow.Launcher public void ShellRun(string cmd, string filename = "cmd.exe") { - var startInfo = ShellCommand.SetProcessStartInfo(filename, arguments: $"/C {cmd}", createNoWindow: true); + var args = filename == "cmd.exe" ? $"/C {cmd}" : $"{cmd}"; + + var startInfo = ShellCommand.SetProcessStartInfo(filename, arguments: args, createNoWindow: true); ShellCommand.Execute(startInfo); } 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 08/31] 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 cd1ab4571..d87a015a9 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -302,6 +302,37 @@ namespace Flow.Launcher.Plugin.PluginsManager .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 @@ namespace Flow.Launcher.Plugin.PluginsManager ContextData = x }); + if (Uri.IsWellFormedUriString(searchNameWithoutKeyword, UriKind.Absolute)) + { + return InstallFromWeb(searchNameWithoutKeyword); + } return Search(results, searchNameWithoutKeyword); } @@ -372,8 +407,8 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 09/31] 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 d87a015a9..644309c1e 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -317,6 +317,7 @@ namespace Flow.Launcher.Plugin.PluginsManager { 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 10/31] 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 644309c1e..fe434c4e4 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -315,7 +315,7 @@ namespace Flow.Launcher.Plugin.PluginsManager }; 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 11/31] 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 fe434c4e4..0ebbc2fdb 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -104,7 +104,7 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 12/31] 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 c36a1dcaa..ba08dc3c5 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 0ebbc2fdb..419cae00f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -47,7 +47,6 @@ namespace Flow.Launcher.Plugin.PluginsManager private Task _downloadManifestTask = Task.CompletedTask; - internal Task UpdateManifestAsync() { if (_downloadManifestTask.Status == TaskStatus.Running) @@ -150,7 +149,11 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 13/31] 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 ba08dc3c5..0c0e8ea33 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 419cae00f..546b31111 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -103,7 +103,7 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager { ID = "", Name = fileName.Split(".").First(), + Version = string.Empty, Author = "N/A", UrlDownload = url }; @@ -411,11 +416,15 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 14/31] 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 0c0e8ea33..fc4ff95ab 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 546b31111..f13e8d8ac 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -9,6 +9,7 @@ using System; 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 @@ namespace Flow.Launcher.Plugin.PluginsManager } 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager return ShouldHideWindow; } }; + return new List { result }; } @@ -356,6 +371,10 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 15/31] 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 ea2119e60..4af344267 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 @@ namespace Flow.Launcher.Core.Plugin } } } - - 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 16/31] 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 fc4ff95ab..89ed9acf3 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 f13e8d8ac..adc4beb6c 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 17/31] 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 89ed9acf3..a30b8e966 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 89a8e0ff5..f445826fa 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -55,7 +55,7 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 adc4beb6c..f37dd86ea 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -166,17 +166,12 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 9c5b0d29f..a951010c0 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 8ca4c614a..11303f472 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/ViewModels/SettingsViewModel.cs @@ -14,5 +14,11 @@ namespace Flow.Launcher.Plugin.PluginsManager.ViewModels 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 89d27f6ff..d75803066 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 703682e07..26668cc05 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 @@ namespace Flow.Launcher.Plugin.PluginsManager.Views 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 18/31] 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 4af344267..dd6517a7f 100644 --- a/Flow.Launcher.Core/Plugin/PluginConfig.cs +++ b/Flow.Launcher.Core/Plugin/PluginConfig.cs @@ -59,7 +59,7 @@ namespace Flow.Launcher.Core.Plugin 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 000000000..28a0ffcb4 --- /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 299a837ee..000000000 --- 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 19/31] 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 28a0ffcb4..d6ba48f19 100644 --- a/Flow.Launcher.Test/PluginLoadTest.cs +++ b/Flow.Launcher.Test/PluginLoadTest.cs @@ -42,12 +42,12 @@ namespace Flow.Launcher.Test }, new PluginMetadata { - ID = "CEA0TYUC6D3B7855823D60DC76F28855", + ID = "ABC0TYUC6D3B7855823D60DC76F28855", Version = "1.0.0" }, new PluginMetadata { - ID = "CEA0TYUC6D3B7855823D60DC76F28855", + ID = "ABC0TYUC6D3B7855823D60DC76F28855", Version = "1.0.0" } }; @@ -59,7 +59,8 @@ namespace Flow.Launcher.Test 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 20/31] 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 a30b8e966..a15c50ccf 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 52cd784ee..4f37dfe83 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 6a060a7fe..d74ab008f 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 f37dd86ea..c02780383 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -150,17 +150,11 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 21/31] 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 592025103..bf1ae5d8e 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 22/31] 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 c02780383..60059c7e9 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -555,8 +555,8 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 16c30e9803004038316e0e373465829da1e6d98c Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Thu, 25 Nov 2021 15:47:11 -0600 Subject: [PATCH 23/31] Refactor Shell Command --- .../SharedCommands/ShellCommand.cs | 13 --- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 90 +++++++++++-------- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs b/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs index c5d43a3d9..8a8c5793d 100644 --- a/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs +++ b/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs @@ -59,18 +59,5 @@ namespace Flow.Launcher.Plugin.SharedCommands GetWindowText(hwnd, sb, sb.Capacity); return sb.ToString(); } - - public static ProcessStartInfo SetProcessStartInfo(this string fileName, string workingDirectory = "", string arguments = "", string verb = "") - { - var info = new ProcessStartInfo - { - FileName = fileName, - WorkingDirectory = workingDirectory, - Arguments = arguments, - Verb = verb - }; - - return info; - } } } diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index f9fc239a5..9af5bfec8 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -193,51 +193,63 @@ namespace Flow.Launcher.Plugin.Shell var workingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); var runAsAdministratorArg = !runAsAdministrator && !_settings.RunAsAdministrator ? "" : "runas"; - ProcessStartInfo info; - if (_settings.Shell == Shell.Cmd) + ProcessStartInfo info = new() { - var arguments = _settings.LeaveShellOpen ? $"/k \"{command}\"" : $"/c \"{command}\" & pause"; - - info = ShellCommand.SetProcessStartInfo("cmd.exe", workingDirectory, arguments, runAsAdministratorArg); - } - else if (_settings.Shell == Shell.Powershell) + Verb = runAsAdministratorArg, + WorkingDirectory = workingDirectory, + }; + switch (_settings.Shell) { - string arguments; - if (_settings.LeaveShellOpen) - { - arguments = $"-NoExit \"{command}\""; - } - else - { - arguments = $"\"{command} ; Read-Host -Prompt \\\"Press Enter to continue\\\"\""; - } - - info = ShellCommand.SetProcessStartInfo("powershell.exe", workingDirectory, arguments, runAsAdministratorArg); - } - else if (_settings.Shell == Shell.RunCommand) - { - var parts = command.Split(new[] { ' ' }, 2); - if (parts.Length == 2) - { - var filename = parts[0]; - if (ExistInPath(filename)) + case Shell.Cmd: { - var arguments = parts[1]; - info = ShellCommand.SetProcessStartInfo(filename, workingDirectory, arguments, runAsAdministratorArg); + info.FileName = "cmd.exe"; + info.ArgumentList.Add(_settings.LeaveShellOpen ? "/k" : "/c"); + info.ArgumentList.Add(command); + break; } - else + + case Shell.Powershell: { - info = ShellCommand.SetProcessStartInfo(command, verb: runAsAdministratorArg); + info.FileName = "powershell.exe"; + if (_settings.LeaveShellOpen) + { + info.ArgumentList.Add("-NoExit"); + info.ArgumentList.Add(command); + } + else + { + info.ArgumentList.Add("-Command"); + info.ArgumentList.Add(command); + } + break; } - } - else - { - info = ShellCommand.SetProcessStartInfo(command, verb: runAsAdministratorArg); - } - } - else - { - throw new NotImplementedException(); + + case Shell.RunCommand: + { + var parts = command.Split(new[] { ' ' }, 2); + if (parts.Length == 2) + { + var filename = parts[0]; + if (ExistInPath(filename)) + { + var arguments = parts[1]; + info.FileName = filename; + info.ArgumentList.Add(arguments); + } + else + { + info.FileName = command; + } + } + else + { + info.FileName = command; + } + + break; + } + default: + throw new NotImplementedException(); } info.UseShellExecute = true; From b4f06caef53a308a3cf5de89fd3f0ab174d6ce86 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Thu, 25 Nov 2021 15:54:00 -0600 Subject: [PATCH 24/31] revert method removal --- Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs b/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs index 8a8c5793d..c5d43a3d9 100644 --- a/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs +++ b/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs @@ -59,5 +59,18 @@ namespace Flow.Launcher.Plugin.SharedCommands GetWindowText(hwnd, sb, sb.Capacity); return sb.ToString(); } + + public static ProcessStartInfo SetProcessStartInfo(this string fileName, string workingDirectory = "", string arguments = "", string verb = "") + { + var info = new ProcessStartInfo + { + FileName = fileName, + WorkingDirectory = workingDirectory, + Arguments = arguments, + Verb = verb + }; + + return info; + } } } From ea179e54552f0d1c0881f99aa10522c47bf67b18 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 29 Nov 2021 06:06:08 +1100 Subject: [PATCH 25/31] 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 60059c7e9..8db54de35 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -555,8 +555,7 @@ namespace Flow.Launcher.Plugin.PluginsManager 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); } } } From 056bffeda9df79b7eb14b57a68b4d0c4fcae643b Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 29 Nov 2021 06:34:58 +1100 Subject: [PATCH 26/31] Shell version bump --- Plugins/Flow.Launcher.Plugin.Shell/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json index 6b20eeef9..b71dba2da 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json @@ -4,7 +4,7 @@ "Name": "Shell", "Description": "Provide executing commands from Flow Launcher", "Author": "qianlifeng", - "Version": "1.4.5", + "Version": "1.4.6", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Shell.dll", From 83feb096c80ab8076d5d83987860ac5b5bcfbdbe Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 29 Nov 2021 08:07:08 +1100 Subject: [PATCH 27/31] update to constants and change method name to OpenThemeFolder --- Flow.Launcher.Infrastructure/Constant.cs | 4 ++++ Flow.Launcher/MainWindow.xaml.cs | 7 +++---- Flow.Launcher/SettingWindow.xaml | 2 +- Flow.Launcher/SettingWindow.xaml.cs | 10 +++++----- Flow.Launcher/ViewModel/SettingWindowViewModel.cs | 3 --- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Constant.cs b/Flow.Launcher.Infrastructure/Constant.cs index 081dd9909..cd49217a4 100644 --- a/Flow.Launcher.Infrastructure/Constant.cs +++ b/Flow.Launcher.Infrastructure/Constant.cs @@ -35,6 +35,10 @@ namespace Flow.Launcher.Infrastructure public const string DefaultTheme = "Win11Light"; + public const string Light = "Light"; + public const string Dark = "Dark"; + public const string System = "System"; + public const string Themes = "Themes"; public const string Settings = "Settings"; public const string Logs = "Logs"; diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 718606ff7..ef0c8f932 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -16,6 +16,7 @@ using ContextMenuStrip = System.Windows.Forms.ContextMenuStrip; using DragEventArgs = System.Windows.DragEventArgs; using KeyEventArgs = System.Windows.Input.KeyEventArgs; using NotifyIcon = System.Windows.Forms.NotifyIcon; +using Flow.Launcher.Infrastructure; namespace Flow.Launcher { @@ -480,16 +481,14 @@ namespace Flow.Launcher public void InitializeDarkMode() { - if (_settings.DarkMode == "Light") + if (_settings.DarkMode == Constant.Light) { ModernWpf.ThemeManager.Current.ApplicationTheme = ModernWpf.ApplicationTheme.Light; } - else if (_settings.DarkMode == "Dark") + else if (_settings.DarkMode == Constant.Dark) { ModernWpf.ThemeManager.Current.ApplicationTheme = ModernWpf.ApplicationTheme.Dark; } - else - { } } } } \ No newline at end of file diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 9278b5680..e5fbd53c8 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -1949,7 +1949,7 @@ Width="180" Margin="0,0,18,0" HorizontalAlignment="Center" - Click="OpenPluginFolder" + Click="OpenThemeFolder" Content="{DynamicResource OpenThemeFolder}" DockPanel.Dock="Top" /> diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index d8bc4da6a..3505269f2 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -265,7 +265,7 @@ namespace Flow.Launcher Close(); } - private void OpenPluginFolder(object sender, RoutedEventArgs e) + private void OpenThemeFolder(object sender, RoutedEventArgs e) { PluginManager.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Themes)); } @@ -277,7 +277,7 @@ namespace Flow.Launcher private void OpenLogFolder(object sender, RoutedEventArgs e) { - PluginManager.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Logs)); + PluginManager.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Logs, Constant.Version)); } private void OnPluginStoreRefreshClick(object sender, RoutedEventArgs e) @@ -308,9 +308,9 @@ namespace Flow.Launcher private void DarkModeSelectedIndexChanged(object sender, EventArgs e) => ThemeManager.Current.ApplicationTheme = settings.DarkMode switch { - "Light" => ApplicationTheme.Light, - "Dark" => ApplicationTheme.Dark, - "System" => null, + Constant.Light => ApplicationTheme.Light, + Constant.Dark => ApplicationTheme.Dark, + Constant.System => null, _ => ThemeManager.Current.ApplicationTheme }; diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index 5a0d816b9..96c14ebe0 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -15,12 +15,10 @@ using Flow.Launcher.Core.Plugin; using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; -using ApplicationTheme = ModernWpf.ApplicationTheme; namespace Flow.Launcher.ViewModel { @@ -387,7 +385,6 @@ namespace Flow.Launcher.ViewModel } } - public ResultsViewModel PreviewResults { get From 489e739a508ad6ecee8f881ecae01c823dade348 Mon Sep 17 00:00:00 2001 From: DB p Date: Mon, 29 Nov 2021 12:22:23 +0900 Subject: [PATCH 28/31] Add Korean String / Change some hardcoded text to string / Remove Darkmode Tip --- Flow.Launcher/Languages/en.xaml | 11 ++-- Flow.Launcher/Languages/ko.xaml | 104 +++++++++++++++++++++---------- Flow.Launcher/SettingWindow.xaml | 5 +- 3 files changed, 78 insertions(+), 42 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 9b2827d5e..e7803ae9b 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -55,15 +55,17 @@ Off Action keyword Setting Action keyword - Current action keyword: - New action keyword: - Current Priority: - New Priority: + Current action keyword + New action keyword + Current Priority + New Priority Priority Plugin Directory Author: Init time: Query time: + | Version + Website @@ -85,7 +87,6 @@ Theme Folder Open Theme Folder Dark Mode - System settings will take effect from the next run System Default Light Dark diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml index 649895cea..2c3e733ed 100644 --- a/Flow.Launcher/Languages/ko.xaml +++ b/Flow.Launcher/Languages/ko.xaml @@ -1,7 +1,8 @@ - - + + 핫키 등록 실패: {0} {0}을 실행할 수 없습니다. Flow Launcher 플러그인 파일 형식이 유효하지 않습니다. @@ -14,8 +15,9 @@ 정보 종료 닫기 + 게임 모드 - + Flow Launcher 설정 일반 포터블 모드 @@ -33,41 +35,48 @@ 표시할 결과 수 전체화면 모드에서는 핫키 무시 게이머라면 켜는 것을 추천합니다. + 기본 파일관리자 + 폴더를 열 때 사용할 파일관리자를 선택하세요. Python 디렉토리 자동 업데이트 선택 시작 시 Flow Launcher 숨김 트레이 아이콘 숨기기 - 쿼리 검색 정확도 - 검색 결과가 좀 더 정확해집니다. + 쿼리 검색 정밀도 + 검색 결과에 필요한 최소 매치 점수를 변경합니다. 항상 Pinyin 사용 Pinyin을 사용하여 검색할 수 있습니다. Pinyin(병음)은 로마자 중국어 입력 방식입니다. 반투명 흐림 효과를 사용하는 경우, 그림자 효과를 쓸 수 없습니다. - + 플러그인 플러그인 더 찾아보기 - On - Off + + 액션 키워드 + 현재 액션 키워드 + 새 액션 키워드 현재 중요도: 새 중요도: 중요도 - 플러그인 디렉토리 - 저자 + 플러그인 폴더 + 제작자 초기화 시간: 쿼리 시간: - - - + | 버전 + 웹사이트 + + + 플러그인 스토어 새로고침 설치 - + 테마 - 테마 더 찾아보기 + 테마 갤러리 + 테마 제작 안내 Hi There 쿼리 상자 글꼴 결과 항목 글꼴 @@ -77,8 +86,17 @@ {0} 테마 로드에 실패했습니다. 기본 테마로 변경합니다. 테마 폴더 테마 폴더 열기 + 다크 모드 + System settings will take effect from the next run + 시스템 기본 + 밝게 + 어둡게 + 소리 효과 + 검색창을 열 때 작은 소리를 재생합니다. + 애니메이션 + 일부 UI에 애니메이션을 사용합니다. - + 핫키 Flow Launcher 핫키 Flow Launcher를 열 때 사용할 단축키를 입력합니다. @@ -87,7 +105,7 @@ 단축키 표시 결과창에서 결과 선택 단축키를 표시합니다. 사용자지정 쿼리 핫키 - Query + 쿼리 삭제 편집 추가 @@ -95,10 +113,11 @@ {0} 플러그인 핫키를 삭제하시겠습니까? 그림자 효과 그림자 효과는 GPU를 사용합니다. 컴퓨터 퍼포먼스가 제한적인 경우 사용을 추천하지 않습니다. + 창 넓이 플루언트 아이콘 사용 결과 및 일부 메뉴에서 플루언트 아이콘을 사용합니다. - + HTTP 프록시 HTTP 프록시 켜기 HTTP 서버 @@ -114,26 +133,41 @@ 프록시 설정 정상 프록시 연결 실패 - + 정보 웹사이트 + Github + 문서 버전 Flow Launcher를 {0}번 실행했습니다. 업데이트 확인 새 버전({0})이 있습니다. Flow Launcher를 재시작하세요. 업데이트 확인을 실패했습니다. api.github.com로의 연결 또는 프록시 설정을 확인해주세요. - 업데이트 다운로드에 실패했습니다. github-cloud.s3.amazonaws.com의 연결 또는 프록시 설정을 확인해주세요. + 업데이트 다운로드에 실패했습니다. github-cloud.s3.amazonaws.com의 연결 또는 프록시 설정을 확인해주세요. 수동 다운로드를 하려면 https://github.com/Flow-Launcher/Flow.Launcher/releases 으로 방문하세요. - 릴리즈 노트: - 사용 팁: + 릴리즈 노트 + 사용 팁 + 개발자도구 + 설정 폴더 + 로그 폴더 - + + 파일관리자 선택 + 사용하려는 파일관리자를 선택하고 필요한 경우 인수를 추가하세요. 기본 인수는 "%d" 이며 해당 위치에 경로가 입력됩니다. 예를들어 "totalcmd.exe /A c:\windows"와 같은 명령이 필요한 경우, 인수는 /A "%d" 입니다. + "%f"는 특정 파일의 경로를 나타냅니다. 파일관리자에서 선택한 파일/폴더의 위치를 강조하는 기능에서 사용됩니다. 이 인수는 "파일경로 인수" 항목에서만 사용할 수 있습니다. 파일관리자에 해당 기능이 없거나 잘 모를 경우 "%d" 인수를 사용할 수 있습니다. + 파일관리자 + 프로필 이름 + 파일관리자 경로 + 폴더경로 인수 + 파일경로 인수 + + 중요도 변경 높은 수를 넣을수록 상위 결과에 표시됩니다. 5를 시도해보세요. 다른 플러그인 보다 결과를 낮추고 싶다면, 그보다 낮은 수를 입력하세요. 중요도에 올바른 정수를 입력하세요. - + 예전 액션 키워드 새 액션 키워드 취소 @@ -145,17 +179,17 @@ 성공적으로 완료했습니다. 액션 키워드를 지정하지 않으려면 *를 사용하세요. - + 커스텀 플러그인 핫키 미리보기 핫키를 사용할 수 없습니다. 다른 핫키를 입력하세요. 플러그인 핫키가 유효하지 않습니다. 업데이트 - + 핫키를 사용할 수 없습니다. - + 버전 시간 수정을 위해 애플리케이션이 어떻게 충돌했는지 알려주세요. @@ -170,17 +204,19 @@ 보고서를 정상적으로 보냈습니다. 보고서를 보내지 못했습니다. Flow Launcher에 문제가 발생했습니다. - - + + 잠시 기다려주세요... - + 새 업데이트 확인 중 새 Flow Launcher 버전({0})을 사용할 수 있습니다. 이미 가장 최신 버전의 Flow Launcher를 사용중입니다. 업데이트 발견 업데이트 중... - Flow Launcher가 유저 정보 데이터를 새버전으로 옮길 수 없습니다. - 프로필 데이터 폴더를 수동으로 {0} 에서 {1}로 옮겨주세요. + + Flow Launcher가 유저 정보 데이터를 새버전으로 옮길 수 없습니다. + 프로필 데이터 폴더를 수동으로 {0} 에서 {1}로 옮겨주세요. + 새 업데이트 소프트웨어 업데이트를 설치하는 중에 오류가 발생했습니다. 업데이트 diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index e5fbd53c8..e3fc1b334 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -1169,7 +1169,7 @@ VerticalAlignment="Center" FontSize="11" Foreground="{DynamicResource PluginInfoColor}" - Text="| version" /> + Text="{DynamicResource plugin_query_version}" /> - + @@ -1920,7 +1920,6 @@ - Date: Mon, 29 Nov 2021 12:38:01 +0900 Subject: [PATCH 29/31] Add Korean String / Adjust button size and color / Change Action Keyword Height to responsive --- Flow.Launcher/ActionKeywords.xaml | 11 ++++++----- Flow.Launcher/Languages/ko.xaml | 5 +++-- Flow.Launcher/PriorityChangeWindow.xaml | 7 ++++--- Flow.Launcher/SelectFileManagerWindow.xaml | 8 +++----- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Flow.Launcher/ActionKeywords.xaml b/Flow.Launcher/ActionKeywords.xaml index 3d0e00459..e94aac9f6 100644 --- a/Flow.Launcher/ActionKeywords.xaml +++ b/Flow.Launcher/ActionKeywords.xaml @@ -4,12 +4,12 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="{DynamicResource actionKeywordsTitle}" Width="450" - Height="345" Background="{DynamicResource PopuBGColor}" Foreground="{DynamicResource PopupTextColor}" Icon="Images\app.png" Loaded="ActionKeyword_OnLoaded" ResizeMode="NoResize" + SizeToContent="Height" WindowStartupLocation="CenterScreen"> @@ -91,7 +91,7 @@ FontWeight="SemiBold" Foreground="{DynamicResource Color05B}" /> - + diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml index 2c3e733ed..4df5d67de 100644 --- a/Flow.Launcher/Languages/ko.xaml +++ b/Flow.Launcher/Languages/ko.xaml @@ -165,7 +165,7 @@ 중요도 변경 - 높은 수를 넣을수록 상위 결과에 표시됩니다. 5를 시도해보세요. 다른 플러그인 보다 결과를 낮추고 싶다면, 그보다 낮은 수를 입력하세요. + 높은 수를 넣을수록 상위 결과에 표시됩니다. 5를 시도해보세요. 다른 플러그인 보다 결과를 낮춰 표시하고 싶다면, 그보다 낮은 수를 입력하세요. 중요도에 올바른 정수를 입력하세요. 예전 액션 키워드 @@ -177,10 +177,11 @@ 새 액션 키워드가 할당된 플러그인이 이미 있습니다. 다른 액션 키워드를 입력하세요. 성공 성공적으로 완료했습니다. - 액션 키워드를 지정하지 않으려면 *를 사용하세요. + 플러그인을 시작하는데 필요한 액션 키워드를 입력하세요. 액션 키워드를 지정하지 않으려면 *를 사용하세요. 이 경우 키워드를 입력하지 않아도 동작합니다. 커스텀 플러그인 핫키 + 단축키를 지정하여 특정 쿼리를 자동으로 입력할 수 있습니다. 사용하고 싶은 단축키를 눌러 지정한 후, 사용할 쿼리를 입력하세요. 미리보기 핫키를 사용할 수 없습니다. 다른 핫키를 입력하세요. 플러그인 핫키가 유효하지 않습니다. diff --git a/Flow.Launcher/PriorityChangeWindow.xaml b/Flow.Launcher/PriorityChangeWindow.xaml index d8fda81e3..8fb27c470 100644 --- a/Flow.Launcher/PriorityChangeWindow.xaml +++ b/Flow.Launcher/PriorityChangeWindow.xaml @@ -104,17 +104,18 @@ diff --git a/Flow.Launcher/SelectFileManagerWindow.xaml b/Flow.Launcher/SelectFileManagerWindow.xaml index 6092c1da1..7380baa6a 100644 --- a/Flow.Launcher/SelectFileManagerWindow.xaml +++ b/Flow.Launcher/SelectFileManagerWindow.xaml @@ -239,21 +239,19 @@