From 1b31e9c9685abd0d1d556d260425fac4b5aff165 Mon Sep 17 00:00:00 2001 From: Odotocodot <48138990+Odotocodot@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:37:05 +0000 Subject: [PATCH 001/230] Create Flow Launcher Theme Selector plugin --- ...w.Launcher.Plugin.FlowThemeSelector.csproj | 37 +++++++ .../Main.cs | 91 ++++++++++++++++++ .../icon.png | Bin 0 -> 6625 bytes .../plugin.json | 12 +++ 4 files changed, 140 insertions(+) create mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj create mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs create mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/icon.png create mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj new file mode 100644 index 000000000..ba0ddd6ab --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj @@ -0,0 +1,37 @@ + + + + + Library + net7.0-windows + true + false + + + + ..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.FlowThemeSelector + + + + ..\..\Output\Release\Plugins\Flow.Launcher.Plugin.FlowThemeSelector + + + + + + + + + + + PreserveNewest + + + + + + PreserveNewest + + + + diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs new file mode 100644 index 000000000..6fd6472db --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Flow.Launcher.Core.Resource; + +namespace Flow.Launcher.Plugin.FlowThemeSelector +{ + public class FlowThemeSelector : IPlugin, IReloadable, IDisposable + { + private PluginInitContext context; + private IEnumerable themes; + + public void Init(PluginInitContext context) + { + this.context = context; + context.API.VisibilityChanged += OnVisibilityChanged; + } + + public List Query(Query query) + { + if (query.IsReQuery) + { + LoadThemes(); + } + + if (string.IsNullOrWhiteSpace(query.Search)) + { + return themes.Select(CreateThemeResult) + .OrderBy(x => x.Title) + .ToList(); + } + + return themes.Select(theme => (theme, matchResult: context.API.FuzzySearch(query.Search, theme))) + .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) + .Select(x => CreateThemeResult(x.theme, x.matchResult.Score, x.matchResult.MatchData)) + .OrderBy(x => x.Title) + .ToList(); + } + + private void OnVisibilityChanged(object sender, VisibilityChangedEventArgs args) + { + if (args.IsVisible && !context.CurrentPluginMetadata.Disabled) + { + LoadThemes(); + } + } + + public void LoadThemes() => themes = ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension); + + public static Result CreateThemeResult(string theme) => CreateThemeResult(theme, 0, null); + + public static Result CreateThemeResult(string theme, int score, IList highlightData) + { + string title; + if (theme == ThemeManager.Instance.Settings.Theme) + { + title = $"{theme} ★"; + score = 2000; + } + else + { + title = theme; + } + + return new Result + { + Title = title, + TitleHighlightData = highlightData, + Glyph = new GlyphInfo("/Resources/#Segoe Fluent Icons", "\ue790"), + Score = score, + Action = c => + { + ThemeManager.Instance.ChangeTheme(theme); + return true; + } + }; + } + + public void ReloadData() => LoadThemes(); + + public void Dispose() + { + if (context != null && context.API != null) + { + context.API.VisibilityChanged -= OnVisibilityChanged; + } + } + + } +} diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/icon.png b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..704e9474eb29ffa1fcaeff9e24c60ee35155afd5 GIT binary patch literal 6625 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 literal 0 HcmV?d00001 diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json new file mode 100644 index 000000000..f275d129c --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json @@ -0,0 +1,12 @@ +{ + "ID": "4DFA743E1086414BAB0AA3071D561D75", + "ActionKeyword": "flowtheme", + "Name": "Flow Launcher Theme Selector", + "Description": "Quickly switch your Flow Launcher theme.", + "Author": "Odotocodot", + "Version": "1.0.0", + "Language": "csharp", + "Website": "https://github.com/Flow-Launcher/Flow.Launcher", + "IcoPath": "icon.png", + "ExecuteFileName": "Flow.Launcher.Plugin.FlowThemeSelector.dll" +} \ No newline at end of file From 49a71d7d53a3c66a3feac30f743f625f47059f83 Mon Sep 17 00:00:00 2001 From: Odotocodot <48138990+Odotocodot@users.noreply.github.com> Date: Sat, 15 Jun 2024 12:16:36 +0100 Subject: [PATCH 002/230] Move Theme Selector into Sys plugin --- ...w.Launcher.Plugin.FlowThemeSelector.csproj | 37 ------------------ .../plugin.json | 12 ------ .../Flow.Launcher.Plugin.Sys.csproj | 1 + .../Images/theme_selector.png} | Bin .../Languages/en.xaml | 4 +- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 29 +++++++++++++- .../ThemeSelector.cs} | 24 +++++++----- 7 files changed, 45 insertions(+), 62 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj delete mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json rename Plugins/{Flow.Launcher.Plugin.FlowThemeSelector/icon.png => Flow.Launcher.Plugin.Sys/Images/theme_selector.png} (100%) rename Plugins/{Flow.Launcher.Plugin.FlowThemeSelector/Main.cs => Flow.Launcher.Plugin.Sys/ThemeSelector.cs} (72%) diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj deleted file mode 100644 index ba0ddd6ab..000000000 --- a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj +++ /dev/null @@ -1,37 +0,0 @@ - - - - - Library - net7.0-windows - true - false - - - - ..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.FlowThemeSelector - - - - ..\..\Output\Release\Plugins\Flow.Launcher.Plugin.FlowThemeSelector - - - - - - - - - - - PreserveNewest - - - - - - PreserveNewest - - - - diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json deleted file mode 100644 index f275d129c..000000000 --- a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "ID": "4DFA743E1086414BAB0AA3071D561D75", - "ActionKeyword": "flowtheme", - "Name": "Flow Launcher Theme Selector", - "Description": "Quickly switch your Flow Launcher theme.", - "Author": "Odotocodot", - "Version": "1.0.0", - "Language": "csharp", - "Website": "https://github.com/Flow-Launcher/Flow.Launcher", - "IcoPath": "icon.png", - "ExecuteFileName": "Flow.Launcher.Plugin.FlowThemeSelector.dll" -} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj index c7a722189..bba466384 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -38,6 +38,7 @@ + diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/icon.png b/Plugins/Flow.Launcher.Plugin.Sys/Images/theme_selector.png similarity index 100% rename from Plugins/Flow.Launcher.Plugin.FlowThemeSelector/icon.png rename to Plugins/Flow.Launcher.Plugin.Sys/Images/theme_selector.png diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml index 91f32a844..2a266f8f6 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml @@ -27,6 +27,7 @@ Flow Launcher Tips Flow Launcher UserData Folder Toggle Game Mode + Set the Flow Launcher Theme Shutdown Computer @@ -49,8 +50,9 @@ Visit Flow Launcher's documentation for more help and how to use tips Open the location where Flow Launcher's settings are stored Toggle Game Mode + Quickly change the Flow Launcher theme - + Success All Flow Launcher settings saved Reloaded all applicable plugin data diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 1ec07915d..0dbb46be9 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -18,9 +18,10 @@ using MessageBox = System.Windows.MessageBox; namespace Flow.Launcher.Plugin.Sys { - public class Main : IPlugin, ISettingProvider, IPluginI18n + public class Main : IPlugin, ISettingProvider, IPluginI18n, IDisposable { private PluginInitContext context; + private ThemeSelector themeSelector; private Dictionary KeywordTitleMappings = new Dictionary(); #region DllImport @@ -58,6 +59,11 @@ namespace Flow.Launcher.Plugin.Sys public List Query(Query query) { + if(query.Search.StartsWith(ThemeSelector.Keyword)) + { + return themeSelector.Query(query); + } + var commands = Commands(); var results = new List(); foreach (var c in commands) @@ -106,6 +112,7 @@ namespace Flow.Launcher.Plugin.Sys public void Init(PluginInitContext context) { this.context = context; + themeSelector = new ThemeSelector(context); KeywordTitleMappings = new Dictionary{ {"Shutdown", "flowlauncher_plugin_sys_shutdown_computer_cmd"}, {"Restart", "flowlauncher_plugin_sys_restart_computer_cmd"}, @@ -126,7 +133,8 @@ namespace Flow.Launcher.Plugin.Sys {"Open Log Location", "flowlauncher_plugin_sys_open_log_location_cmd"}, {"Flow Launcher Tips", "flowlauncher_plugin_sys_open_docs_tips_cmd"}, {"Flow Launcher UserData Folder", "flowlauncher_plugin_sys_open_userdata_location_cmd"}, - {"Toggle Game Mode", "flowlauncher_plugin_sys_toggle_game_mode_cmd"} + {"Toggle Game Mode", "flowlauncher_plugin_sys_toggle_game_mode_cmd"}, + {"Set Flow Launcher Theme", "flowlauncher_plugin_sys_theme_selector_cmd"} }; } @@ -426,6 +434,18 @@ namespace Flow.Launcher.Plugin.Sys context.API.ToggleGameMode(); return true; } + }, + new Result + { + Title = "Set Flow Launcher Theme", + SubTitle = context.API.GetTranslation("flowlauncher_plugin_sys_theme_selector"), + IcoPath = "Images\\theme_selector.png", + Glyph = new GlyphInfo("/Resources/#Segoe Fluent Icons", "\ue790"), + Action = c => + { + context.API.ChangeQuery($"{ThemeSelector.Keyword} "); + return false; + } } }); @@ -441,5 +461,10 @@ namespace Flow.Launcher.Plugin.Sys { return context.API.GetTranslation("flowlauncher_plugin_sys_plugin_description"); } + + public void Dispose() + { + themeSelector.Dispose(); + } } } diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs similarity index 72% rename from Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs rename to Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 6fd6472db..24d17486e 100644 --- a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -4,14 +4,16 @@ using System.IO; using System.Linq; using Flow.Launcher.Core.Resource; -namespace Flow.Launcher.Plugin.FlowThemeSelector +namespace Flow.Launcher.Plugin.Sys { - public class FlowThemeSelector : IPlugin, IReloadable, IDisposable + public class ThemeSelector : IReloadable, IDisposable { - private PluginInitContext context; + public const string Keyword = "fltheme"; + + private readonly PluginInitContext context; private IEnumerable themes; - public void Init(PluginInitContext context) + public ThemeSelector(PluginInitContext context) { this.context = context; context.API.VisibilityChanged += OnVisibilityChanged; @@ -24,14 +26,16 @@ namespace Flow.Launcher.Plugin.FlowThemeSelector LoadThemes(); } - if (string.IsNullOrWhiteSpace(query.Search)) + string search = query.Search[(query.Search.IndexOf(Keyword, StringComparison.Ordinal) + Keyword.Length + 1)..]; + + if (string.IsNullOrWhiteSpace(search)) { return themes.Select(CreateThemeResult) .OrderBy(x => x.Title) .ToList(); } - return themes.Select(theme => (theme, matchResult: context.API.FuzzySearch(query.Search, theme))) + return themes.Select(theme => (theme, matchResult: context.API.FuzzySearch(search, theme))) .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) .Select(x => CreateThemeResult(x.theme, x.matchResult.Score, x.matchResult.MatchData)) .OrderBy(x => x.Title) @@ -46,11 +50,12 @@ namespace Flow.Launcher.Plugin.FlowThemeSelector } } - public void LoadThemes() => themes = ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension); + private void LoadThemes() + => themes = ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension); - public static Result CreateThemeResult(string theme) => CreateThemeResult(theme, 0, null); + private static Result CreateThemeResult(string theme) => CreateThemeResult(theme, 0, null); - public static Result CreateThemeResult(string theme, int score, IList highlightData) + private static Result CreateThemeResult(string theme, int score, IList highlightData) { string title; if (theme == ThemeManager.Instance.Settings.Theme) @@ -86,6 +91,5 @@ namespace Flow.Launcher.Plugin.FlowThemeSelector context.API.VisibilityChanged -= OnVisibilityChanged; } } - } } From 7a0be2c6103939312eeead86c3a1e01a3d618a3f Mon Sep 17 00:00:00 2001 From: Odotocodot <48138990+Odotocodot@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:50:00 +0100 Subject: [PATCH 003/230] Remove Reloadable from theme selector --- Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 24d17486e..758250421 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -6,7 +6,7 @@ using Flow.Launcher.Core.Resource; namespace Flow.Launcher.Plugin.Sys { - public class ThemeSelector : IReloadable, IDisposable + public class ThemeSelector : IDisposable { public const string Keyword = "fltheme"; @@ -82,8 +82,6 @@ namespace Flow.Launcher.Plugin.Sys }; } - public void ReloadData() => LoadThemes(); - public void Dispose() { if (context != null && context.API != null) From 5a80adcbfec1309b537721ab9e98f9d07187c135 Mon Sep 17 00:00:00 2001 From: Kevin Zhang <45326534+taooceros@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:59:43 -0600 Subject: [PATCH 004/230] Send a reload request with ctx when reloading --- Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs index 5a6633525..ae4fd639d 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs @@ -133,10 +133,16 @@ namespace Flow.Launcher.Core.Plugin RPC.StartListening(); } - public virtual Task ReloadDataAsync() + public virtual async Task ReloadDataAsync() { SetupJsonRPC(); - return Task.CompletedTask; + try + { + await RPC.InvokeAsync("reload", context); + } + catch (RemoteMethodNotFoundException e) + { + } } public virtual async ValueTask DisposeAsync() From fa8cd548f6c11d71cf9dbd91a5c6c1495837222b Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Thu, 5 Dec 2024 14:18:13 +0600 Subject: [PATCH 005/230] Add `.`, `./lib`, `./plugin` directories to path for Python plugins --- Flow.Launcher.Core/Plugin/PythonPlugin.cs | 52 ++++++++++++++++++--- Flow.Launcher.Core/Plugin/PythonPluginV2.cs | 31 +++++++++++- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PythonPlugin.cs b/Flow.Launcher.Core/Plugin/PythonPlugin.cs index 536e69b3d..36160b920 100644 --- a/Flow.Launcher.Core/Plugin/PythonPlugin.cs +++ b/Flow.Launcher.Core/Plugin/PythonPlugin.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; using System.IO; using System.Text.Json; using System.Threading; @@ -29,10 +30,6 @@ namespace Flow.Launcher.Core.Plugin _startInfo.EnvironmentVariables["FLOW_VERSION"] = Constant.Version; _startInfo.EnvironmentVariables["FLOW_PROGRAM_DIRECTORY"] = Constant.ProgramDirectory; _startInfo.EnvironmentVariables["FLOW_APPLICATION_DIRECTORY"] = Constant.ApplicationDirectory; - - - //Add -B flag to tell python don't write .py[co] files. Because .pyc contains location infos which will prevent python portable - _startInfo.ArgumentList.Add("-B"); } protected override Task RequestAsync(JsonRPCRequestModel request, CancellationToken token = default) @@ -50,10 +47,51 @@ namespace Flow.Launcher.Core.Plugin // TODO: Async Action return Execute(_startInfo); } + public override async Task InitAsync(PluginInitContext context) { - _startInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath); - _startInfo.ArgumentList.Add(""); + // Run .py files via `-c ` + if (context.CurrentPluginMetadata.ExecuteFilePath.EndsWith(".py", StringComparison.OrdinalIgnoreCase)) + { + var rootDirectory = context.CurrentPluginMetadata.PluginDirectory; + var libDirectory = Path.Combine(rootDirectory, "lib"); + var pluginDirectory = Path.Combine(rootDirectory, "plugin"); + + // This makes it easier for plugin authors to import their own modules. + // They won't have to add `.`, `./lib`, or `./plugin` to their sys.path manually. + // Instead of running the .py file directly, we pass the code we want to run as a CLI argument. + // This code sets sys.path for the plugin author and then runs the .py file via runpy. + _startInfo.ArgumentList.Add("-c"); + _startInfo.ArgumentList.Add( + $""" + import sys + sys.path.append(r'{rootDirectory}') + sys.path.append(r'{libDirectory}') + sys.path.append(r'{pluginDirectory}') + + import runpy + runpy.run_path(r'{context.CurrentPluginMetadata.ExecuteFilePath}', None, '__main__') + """ + ); + // Plugins always expect the JSON data to be in the third argument + // (we're always setting it as _startInfo.ArgumentList[2] = ...). + _startInfo.ArgumentList.Add(""); + // Because plugins always expect the JSON data to be in the third argument, and specifying -c + // takes up two arguments, we have to move `-B` to the end. + _startInfo.ArgumentList.Add("-B"); + } + // Run .pyz files as is + else + { + // -B flag is needed to tell python not to write .py[co] files. + // Because .pyc contains location infos which will prevent python portable + _startInfo.ArgumentList.Add("-B"); + _startInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath); + // Plugins always expect the JSON data to be in the third argument + // (we're always setting it as _startInfo.ArgumentList[2] = ...). + _startInfo.ArgumentList.Add(""); + } + await base.InitAsync(context); _startInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory; } diff --git a/Flow.Launcher.Core/Plugin/PythonPluginV2.cs b/Flow.Launcher.Core/Plugin/PythonPluginV2.cs index 5c36e0eea..224653ba1 100644 --- a/Flow.Launcher.Core/Plugin/PythonPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/PythonPluginV2.cs @@ -33,7 +33,36 @@ namespace Flow.Launcher.Core.Plugin public override async Task InitAsync(PluginInitContext context) { - StartInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath); + // Run .py files via `-c ` + if (context.CurrentPluginMetadata.ExecuteFilePath.EndsWith(".py", StringComparison.OrdinalIgnoreCase)) + { + var rootDirectory = context.CurrentPluginMetadata.PluginDirectory; + var libDirectory = Path.Combine(rootDirectory, "lib"); + var pluginDirectory = Path.Combine(rootDirectory, "plugin"); + var filePath = context.CurrentPluginMetadata.ExecuteFilePath; + + // This makes it easier for plugin authors to import their own modules. + // They won't have to add `.`, `./lib`, or `./plugin` to their sys.path manually. + // Instead of running the .py file directly, we pass the code we want to run as a CLI argument. + // This code sets sys.path for the plugin author and then runs the .py file via runpy. + StartInfo.ArgumentList.Add("-c"); + StartInfo.ArgumentList.Add( + $""" + import sys + sys.path.append(r'{rootDirectory}') + sys.path.append(r'{libDirectory}') + sys.path.append(r'{pluginDirectory}') + + import runpy + runpy.run_path(r'{filePath}', None, '__main__') + """ + ); + } + // Run .pyz files as is + else + { + StartInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath); + } await base.InitAsync(context); } From d5dd7b44a41322ebdd9e4e97a25e62e653775688 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Thu, 5 Dec 2024 17:37:54 +0600 Subject: [PATCH 006/230] Use PYTHONDONTWRITEBYTECODE instead of -B flag when running Python plugins --- Flow.Launcher.Core/Plugin/PythonPlugin.cs | 11 ++++++----- Flow.Launcher.Core/Plugin/PythonPluginV2.cs | 4 +--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PythonPlugin.cs b/Flow.Launcher.Core/Plugin/PythonPlugin.cs index 36160b920..7b670742a 100644 --- a/Flow.Launcher.Core/Plugin/PythonPlugin.cs +++ b/Flow.Launcher.Core/Plugin/PythonPlugin.cs @@ -26,6 +26,9 @@ namespace Flow.Launcher.Core.Plugin var path = Path.Combine(Constant.ProgramDirectory, JsonRPC); _startInfo.EnvironmentVariables["PYTHONPATH"] = path; + // Prevent Python from writing .py[co] files. + // Because .pyc contains location infos which will prevent python portable. + _startInfo.EnvironmentVariables["PYTHONDONTWRITEBYTECODE"] = "1"; _startInfo.EnvironmentVariables["FLOW_VERSION"] = Constant.Version; _startInfo.EnvironmentVariables["FLOW_PROGRAM_DIRECTORY"] = Constant.ProgramDirectory; @@ -76,15 +79,13 @@ namespace Flow.Launcher.Core.Plugin // Plugins always expect the JSON data to be in the third argument // (we're always setting it as _startInfo.ArgumentList[2] = ...). _startInfo.ArgumentList.Add(""); - // Because plugins always expect the JSON data to be in the third argument, and specifying -c - // takes up two arguments, we have to move `-B` to the end. - _startInfo.ArgumentList.Add("-B"); } // Run .pyz files as is else { - // -B flag is needed to tell python not to write .py[co] files. - // Because .pyc contains location infos which will prevent python portable + // No need for -B flag because we're using PYTHONDONTWRITEBYTECODE env variable now, + // but the plugins still expect data to be sent as the third argument, so we're keeping + // the flag here, even though it's not necessary anymore. _startInfo.ArgumentList.Add("-B"); _startInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath); // Plugins always expect the JSON data to be in the third argument diff --git a/Flow.Launcher.Core/Plugin/PythonPluginV2.cs b/Flow.Launcher.Core/Plugin/PythonPluginV2.cs index 224653ba1..03ac0e661 100644 --- a/Flow.Launcher.Core/Plugin/PythonPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/PythonPluginV2.cs @@ -26,9 +26,7 @@ namespace Flow.Launcher.Core.Plugin var path = Path.Combine(Constant.ProgramDirectory, JsonRpc); StartInfo.EnvironmentVariables["PYTHONPATH"] = path; - - //Add -B flag to tell python don't write .py[co] files. Because .pyc contains location infos which will prevent python portable - StartInfo.ArgumentList.Add("-B"); + StartInfo.EnvironmentVariables["PYTHONDONTWRITEBYTECODE"] = "1"; } public override async Task InitAsync(PluginInitContext context) From 41a345a70006e881709b1c6543e683926289b583 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Fri, 6 Dec 2024 23:55:20 -0600 Subject: [PATCH 007/230] Remove Result comparison and Change signature from IEnumerable to ICollection (due to the potential of multiple enumeration) --- Flow.Launcher.Plugin/Result.cs | 21 --------------------- Flow.Launcher/ViewModel/ResultsViewModel.cs | 6 +++--- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 9b42b1021..ac0b827c0 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -156,27 +156,6 @@ namespace Flow.Launcher.Plugin } } - /// - public override bool Equals(object obj) - { - var r = obj as Result; - - var equality = string.Equals(r?.Title, Title) && - string.Equals(r?.SubTitle, SubTitle) && - string.Equals(r?.AutoCompleteText, AutoCompleteText) && - string.Equals(r?.CopyText, CopyText) && - string.Equals(r?.IcoPath, IcoPath) && - TitleHighlightData == r.TitleHighlightData; - - return equality; - } - - /// - public override int GetHashCode() - { - return HashCode.Combine(Title, SubTitle, AutoCompleteText, CopyText, IcoPath); - } - /// public override string ToString() { diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs index 107372e01..c0e0b146d 100644 --- a/Flow.Launcher/ViewModel/ResultsViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs @@ -182,7 +182,7 @@ namespace Flow.Launcher.ViewModel /// /// To avoid deadlock, this method should not called from main thread /// - public void AddResults(IEnumerable resultsForUpdates, CancellationToken token, bool reselect = true) + public void AddResults(ICollection resultsForUpdates, CancellationToken token, bool reselect = true) { var newResults = NewResults(resultsForUpdates); @@ -228,12 +228,12 @@ namespace Flow.Launcher.ViewModel .ToList(); } - private List NewResults(IEnumerable resultsForUpdates) + private List NewResults(ICollection resultsForUpdates) { if (!resultsForUpdates.Any()) return Results; - return Results.Where(r => r != null && !resultsForUpdates.Any(u => u.ID == r.Result.PluginID)) + return Results.Where(r => r != null && resultsForUpdates.All(u => u.ID != r.Result.PluginID)) .Concat(resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings))) .OrderByDescending(rv => rv.Result.Score) .ToList(); From 51a16cc40f8159f6e54d772df16e5ae0466be989 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Fri, 6 Dec 2024 23:55:20 -0600 Subject: [PATCH 008/230] Remove Result comparison and Change signature from IEnumerable to ICollection (due to the potential of multiple enumeration) --- Flow.Launcher.Plugin/Result.cs | 21 --------------------- Flow.Launcher/ViewModel/ResultsViewModel.cs | 6 +++--- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index f2050cc9f..c6ca81cf3 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -157,27 +157,6 @@ namespace Flow.Launcher.Plugin } } - /// - public override bool Equals(object obj) - { - var r = obj as Result; - - var equality = string.Equals(r?.Title, Title) && - string.Equals(r?.SubTitle, SubTitle) && - string.Equals(r?.AutoCompleteText, AutoCompleteText) && - string.Equals(r?.CopyText, CopyText) && - string.Equals(r?.IcoPath, IcoPath) && - TitleHighlightData == r.TitleHighlightData; - - return equality; - } - - /// - public override int GetHashCode() - { - return HashCode.Combine(Title, SubTitle, AutoCompleteText, CopyText, IcoPath); - } - /// public override string ToString() { diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs index 107372e01..c0e0b146d 100644 --- a/Flow.Launcher/ViewModel/ResultsViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs @@ -182,7 +182,7 @@ namespace Flow.Launcher.ViewModel /// /// To avoid deadlock, this method should not called from main thread /// - public void AddResults(IEnumerable resultsForUpdates, CancellationToken token, bool reselect = true) + public void AddResults(ICollection resultsForUpdates, CancellationToken token, bool reselect = true) { var newResults = NewResults(resultsForUpdates); @@ -228,12 +228,12 @@ namespace Flow.Launcher.ViewModel .ToList(); } - private List NewResults(IEnumerable resultsForUpdates) + private List NewResults(ICollection resultsForUpdates) { if (!resultsForUpdates.Any()) return Results; - return Results.Where(r => r != null && !resultsForUpdates.Any(u => u.ID == r.Result.PluginID)) + return Results.Where(r => r != null && resultsForUpdates.All(u => u.ID != r.Result.PluginID)) .Concat(resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings))) .OrderByDescending(rv => rv.Result.Score) .ToList(); From 5f6ac6a35e38c301ffb2b8b2fdc5af95869b3703 Mon Sep 17 00:00:00 2001 From: Kevin Zhang <45326534+taooceros@users.noreply.github.com> Date: Sat, 7 Dec 2024 12:48:15 -0600 Subject: [PATCH 009/230] Update Flow.Launcher/ViewModel/ResultsViewModel.cs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Flow.Launcher/ViewModel/ResultsViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs index c0e0b146d..7d2b5bc93 100644 --- a/Flow.Launcher/ViewModel/ResultsViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs @@ -233,7 +233,7 @@ namespace Flow.Launcher.ViewModel if (!resultsForUpdates.Any()) return Results; - return Results.Where(r => r != null && resultsForUpdates.All(u => u.ID != r.Result.PluginID)) + return Results.Where(r => r?.Result != null && resultsForUpdates.All(u => u.ID != r.Result.PluginID)) .Concat(resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings))) .OrderByDescending(rv => rv.Result.Score) .ToList(); From 4b9c23d49bcf823641258ab003225edd9face248 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 22:46:08 +0000 Subject: [PATCH 010/230] Bump nunit from 3.14.0 to 4.3.2 Bumps [nunit](https://github.com/nunit/nunit) from 3.14.0 to 4.3.2. - [Release notes](https://github.com/nunit/nunit/releases) - [Changelog](https://github.com/nunit/nunit/blob/main/CHANGES.md) - [Commits](https://github.com/nunit/nunit/compare/v3.14.0...4.3.2) --- updated-dependencies: - dependency-name: nunit dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Flow.Launcher.Test/Flow.Launcher.Test.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj index 8286e142e..0241a374e 100644 --- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj +++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj @@ -49,7 +49,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 921d6a3beb6a3c05ca00e6ce70a41fbf9e98b21b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 2 Jan 2025 18:47:25 +0800 Subject: [PATCH 011/230] Add support for system language item --- .../Resource/Internationalization.cs | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index 1505e84f8..aac6ecc1e 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -18,6 +18,8 @@ namespace Flow.Launcher.Core.Resource { public Settings Settings { get; set; } private const string Folder = "Languages"; + private const string SystemLanguageCode = "System"; + private const string DefaultLanguageCode = "en"; private const string DefaultFile = "en.xaml"; private const string Extension = ".xaml"; private readonly List _languageDirectories = new List(); @@ -68,8 +70,18 @@ namespace Flow.Launcher.Core.Resource public void ChangeLanguage(string languageCode) { languageCode = languageCode.NonNull(); - Language language = GetLanguageByLanguageCode(languageCode); - ChangeLanguage(language); + + // Get actual language if language code is system + var isSystem = false; + if (languageCode == SystemLanguageCode) + { + languageCode = GetSystemLanguageCode(); + isSystem = true; + } + + // Get language by language code and change language + var language = GetLanguageByLanguageCode(languageCode); + ChangeLanguage(language, isSystem); } private Language GetLanguageByLanguageCode(string languageCode) @@ -87,11 +99,10 @@ namespace Flow.Launcher.Core.Resource } } - public void ChangeLanguage(Language language) + private void ChangeLanguage(Language language, bool isSystem) { language = language.NonNull(); - RemoveOldLanguageFiles(); if (language != AvailableLanguages.English) { @@ -103,7 +114,7 @@ namespace Flow.Launcher.Core.Resource CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture; // Raise event after culture is set - Settings.Language = language.LanguageCode; + Settings.Language = isSystem ? SystemLanguageCode : language.LanguageCode; _ = Task.Run(() => { UpdatePluginMetadataTranslations(); @@ -167,7 +178,35 @@ namespace Flow.Launcher.Core.Resource public List LoadAvailableLanguages() { - return AvailableLanguages.GetAvailableLanguages(); + var list = AvailableLanguages.GetAvailableLanguages(); + list.Insert(0, new Language(SystemLanguageCode, "System")); + return list; + } + + private string GetSystemLanguageCode() + { + var availableLanguages = AvailableLanguages.GetAvailableLanguages(); + + // Retrieve the language identifiers for the current culture + var currentCulture = CultureInfo.CurrentCulture; + var twoLetterCode = currentCulture.TwoLetterISOLanguageName; + var threeLetterCode = currentCulture.ThreeLetterISOLanguageName; + var fullName = currentCulture.Name; + + // Try to find a match in the available languages list + foreach (var language in availableLanguages) + { + var languageCode = language.LanguageCode; + + if (string.Equals(languageCode, twoLetterCode, StringComparison.OrdinalIgnoreCase) || + string.Equals(languageCode, threeLetterCode, StringComparison.OrdinalIgnoreCase) || + string.Equals(languageCode, fullName, StringComparison.OrdinalIgnoreCase)) + { + return languageCode; + } + } + + return DefaultLanguageCode; } public string GetTranslation(string key) From 0ae3cfcdd6f735b6f8e16ffa0e782c394fbd2e68 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 2 Jan 2025 18:50:02 +0800 Subject: [PATCH 012/230] Add display translation for system language item --- .../Resource/AvailableLanguages.cs | 34 ++++++++++++++++++- .../Resource/Internationalization.cs | 2 +- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Core/Resource/AvailableLanguages.cs b/Flow.Launcher.Core/Resource/AvailableLanguages.cs index c385cd8e8..ecaecf646 100644 --- a/Flow.Launcher.Core/Resource/AvailableLanguages.cs +++ b/Flow.Launcher.Core/Resource/AvailableLanguages.cs @@ -30,7 +30,6 @@ namespace Flow.Launcher.Core.Resource public static Language Vietnamese = new Language("vi-vn", "Tiếng Việt"); public static Language Hebrew = new Language("he", "עברית"); - public static List GetAvailableLanguages() { List languages = new List @@ -63,5 +62,38 @@ namespace Flow.Launcher.Core.Resource }; return languages; } + + public static string GetSystemTranslation(string languageCode) + { + return languageCode switch + { + "en" => "System", + "zh-cn" => "系统", + "zh-tw" => "系統", + "uk-UA" => "Система", + "ru" => "Система", + "fr" => "Système", + "ja" => "システム", + "nl" => "Systeem", + "pl" => "System", + "da" => "System", + "de" => "System", + "ko" => "시스템", + "sr" => "Систем", + "pt-pt" => "Sistema", + "pt-br" => "Sistema", + "es" => "Sistema", + "es-419" => "Sistema", + "it" => "Sistema", + "nb-NO" => "System", + "sk" => "Systém", + "tr" => "Sistem", + "cs" => "Systém", + "ar" => "النظام", + "vi-vn" => "Hệ thống", + "he" => "מערכת", + _ => "System", + }; + } } } diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index aac6ecc1e..4db3e8633 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -179,7 +179,7 @@ namespace Flow.Launcher.Core.Resource public List LoadAvailableLanguages() { var list = AvailableLanguages.GetAvailableLanguages(); - list.Insert(0, new Language(SystemLanguageCode, "System")); + list.Insert(0, new Language(SystemLanguageCode, AvailableLanguages.GetSystemTranslation(GetSystemLanguageCode()))); return list; } From 37058f765185341a08007d4c713d944e25303b79 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 4 Jan 2025 21:55:44 +0800 Subject: [PATCH 013/230] Improve code quality. --- .../Flow.Launcher.Plugin.PluginsManager/Main.cs | 2 +- .../PluginsManager.cs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index bec84f484..156135f81 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -51,7 +51,7 @@ namespace Flow.Launcher.Plugin.PluginsManager return query.FirstSearch.ToLower() switch { //search could be url, no need ToLower() when passed in - Settings.InstallCommand => await pluginManager.RequestInstallOrUpdate(query.SecondToEndSearch, token, query.IsReQuery), + Settings.InstallCommand => await pluginManager.RequestInstallOrUpdateAsync(query.SecondToEndSearch, token, query.IsReQuery), Settings.UninstallCommand => pluginManager.RequestUninstall(query.SecondToEndSearch), Settings.UpdateCommand => await pluginManager.RequestUpdateAsync(query.SecondToEndSearch, token, query.IsReQuery), _ => pluginManager.GetDefaultHotKeys().Where(hotkey => diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 305d248d3..b1b1a7502 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -324,7 +324,7 @@ namespace Flow.Launcher.Plugin.PluginsManager string.Format( Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), x.Name)); - }, TaskContinuationOptions.OnlyOnFaulted); + }, token, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default); return true; }, @@ -337,7 +337,7 @@ namespace Flow.Launcher.Plugin.PluginsManager }); // Update all result - if (resultsForUpdate.Count() > 1) + if (resultsForUpdate.Count > 1) { var updateAllResult = new Result { @@ -351,13 +351,13 @@ namespace Flow.Launcher.Plugin.PluginsManager { message = string.Format( Context.API.GetTranslation("plugin_pluginsmanager_update_all_prompt"), - resultsForUpdate.Count(), Environment.NewLine); + resultsForUpdate.Count, Environment.NewLine); } else { message = string.Format( Context.API.GetTranslation("plugin_pluginsmanager_update_all_prompt_no_restart"), - resultsForUpdate.Count()); + resultsForUpdate.Count); } if (Context.API.ShowMsgBox(message, @@ -401,7 +401,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_title"), string.Format( Context.API.GetTranslation("plugin_pluginsmanager_update_all_success_restart"), - resultsForUpdate.Count())); + resultsForUpdate.Count)); Context.API.RestartApp(); } else @@ -409,7 +409,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_title"), string.Format( Context.API.GetTranslation("plugin_pluginsmanager_update_all_success_no_restart"), - resultsForUpdate.Count())); + resultsForUpdate.Count)); } return true; @@ -545,7 +545,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.GetAllPlugins().Any(x => x.Metadata.Website.StartsWith(constructedUrlPart)); } - internal async ValueTask> RequestInstallOrUpdate(string search, CancellationToken token, + internal async ValueTask> RequestInstallOrUpdateAsync(string search, CancellationToken token, bool usePrimaryUrlOnly = false) { await PluginsManifest.UpdateManifestAsync(token, usePrimaryUrlOnly); From 562b233c157f2d11bc00f744f2772223037c4eb4 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 4 Jan 2025 23:11:13 +0800 Subject: [PATCH 014/230] Add progress box support for downloading plugin --- Flow.Launcher.Core/ProgressBoxEx.xaml | 106 ++++++++++++++++++ Flow.Launcher.Core/ProgressBoxEx.xaml.cs | 76 +++++++++++++ .../PluginsManager.cs | 59 +++++++++- 3 files changed, 239 insertions(+), 2 deletions(-) create mode 100644 Flow.Launcher.Core/ProgressBoxEx.xaml create mode 100644 Flow.Launcher.Core/ProgressBoxEx.xaml.cs diff --git a/Flow.Launcher.Core/ProgressBoxEx.xaml b/Flow.Launcher.Core/ProgressBoxEx.xaml new file mode 100644 index 000000000..4cce82221 --- /dev/null +++ b/Flow.Launcher.Core/ProgressBoxEx.xaml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +