From 7d5001de1882dec8b678e9830fa64e95567b6118 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 5 Jun 2025 18:16:13 +0800 Subject: [PATCH 01/16] Catch exception when installing Everything --- .../Languages/en.xaml | 3 ++ .../Everything/EverythingSearchManager.cs | 33 ++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index eefd6f4eb..9f60aaa43 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -162,6 +162,9 @@ Do you want to enable content search for Everything? It can be very slow without index (which is only supported in Everything v1.5+) + Unable to find Everything.exe + Failed to install Everything, please install it manually + Native Context Menu Display native context menu (experimental) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index 6c9155539..ce71c94ba 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -11,6 +11,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IPathIndexProvider { + private static readonly string ClassName = nameof(EverythingSearchManager); + private Settings Settings { get; } public EverythingSearchManager(Settings settings) @@ -42,19 +44,32 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything private async ValueTask ClickToInstallEverythingAsync(ActionContext _) { - var installedPath = await EverythingDownloadHelper.PromptDownloadIfNotInstallAsync(Settings.EverythingInstalledPath, Main.Context.API); - - if (installedPath == null) + try { - Main.Context.API.ShowMsgError("Unable to find Everything.exe"); + var installedPath = await EverythingDownloadHelper.PromptDownloadIfNotInstallAsync(Settings.EverythingInstalledPath, Main.Context.API); + + if (installedPath == null) + { + Main.Context.API.ShowMsgError(Main.Context.API.GetTranslation("flowlauncher_plugin_everything_not_found")); + Main.Context.API.LogError(ClassName, "Unable to find Everything.exe"); + + return false; + } + + Settings.EverythingInstalledPath = installedPath; + Process.Start(installedPath, "-startup"); + + return true; + } + // Sometimes Everything installation will fail because of permission issues or file not found issues + // Just let the user know that Everything is not installed properly and ask them to install it manually + catch (Exception e) + { + Main.Context.API.ShowMsgError(Main.Context.API.GetTranslation("flowlauncher_plugin_everything_install_issue")); + Main.Context.API.LogException(ClassName, "Failed to install Everything", e); return false; } - - Settings.EverythingInstalledPath = installedPath; - Process.Start(installedPath, "-startup"); - - return true; } public async IAsyncEnumerable SearchAsync(string search, [EnumeratorCancellation] CancellationToken token) From b2e754dfd56c9dc40765e54c075b132f3ea930e9 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 5 Jun 2025 18:48:26 +0800 Subject: [PATCH 02/16] Fix command issue for pswh.exe --- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 2613c770b..2771a9118 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -242,6 +242,9 @@ namespace Flow.Launcher.Plugin.Shell case Shell.Pwsh: { + // Using just a ; doesn't work with wt, as it's used to create a new tab for the terminal window + // \\ must be escaped for it to work properly, or breaking it into multiple arguments + var addedCharacter = _settings.UseWindowsTerminal ? "\\" : ""; if (_settings.UseWindowsTerminal) { info.FileName = "wt.exe"; @@ -256,7 +259,7 @@ namespace Flow.Launcher.Plugin.Shell info.ArgumentList.Add("-NoExit"); } info.ArgumentList.Add("-Command"); - info.ArgumentList.Add($"{command}\\; {(_settings.CloseShellAfterPress ? $"Write-Host '{Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); + info.ArgumentList.Add($"{command}{addedCharacter}; {(_settings.CloseShellAfterPress ? $"Write-Host '{Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); break; } From d7c7ec8f5ef0fd0ad7472b7df9d204da6784895f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 5 Jun 2025 18:55:58 +0800 Subject: [PATCH 03/16] Apply for all wt.exe --- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 144 +++++++++++---------- 1 file changed, 74 insertions(+), 70 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 2771a9118..d0add9f31 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -201,97 +201,101 @@ namespace Flow.Launcher.Plugin.Shell switch (_settings.Shell) { case Shell.Cmd: - { - if (_settings.UseWindowsTerminal) { - info.FileName = "wt.exe"; - info.ArgumentList.Add("cmd"); - } - else - { - info.FileName = "cmd.exe"; - } + if (_settings.UseWindowsTerminal) + { + info.FileName = "wt.exe"; + info.ArgumentList.Add("cmd"); + } + else + { + info.FileName = "cmd.exe"; + } - info.ArgumentList.Add($"{(_settings.LeaveShellOpen ? "/k" : "/c")} {command} {(_settings.CloseShellAfterPress ? $"&& echo {Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")} && pause > nul /c" : "")}"); - break; - } + info.ArgumentList.Add($"{(_settings.LeaveShellOpen ? "/k" : "/c")} {command} {(_settings.CloseShellAfterPress ? $"&& echo {Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")} && pause > nul /c" : "")}"); + break; + } case Shell.Powershell: - { - if (_settings.UseWindowsTerminal) { - info.FileName = "wt.exe"; - info.ArgumentList.Add("powershell"); + // Using just a ; doesn't work with wt, as it's used to create a new tab for the terminal window + // \\ must be escaped for it to work properly, or breaking it into multiple arguments + var addedCharacter = _settings.UseWindowsTerminal ? "\\" : ""; + if (_settings.UseWindowsTerminal) + { + info.FileName = "wt.exe"; + info.ArgumentList.Add("powershell"); + } + else + { + info.FileName = "powershell.exe"; + } + if (_settings.LeaveShellOpen) + { + info.ArgumentList.Add("-NoExit"); + info.ArgumentList.Add(command); + } + else + { + info.ArgumentList.Add("-Command"); + info.ArgumentList.Add($"{command}{addedCharacter}; {(_settings.CloseShellAfterPress ? $"Write-Host '{Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'{addedCharacter}; [System.Console]::ReadKey(){addedCharacter}; exit" : "")}"); + } + break; } - else - { - info.FileName = "powershell.exe"; - } - if (_settings.LeaveShellOpen) - { - info.ArgumentList.Add("-NoExit"); - info.ArgumentList.Add(command); - } - else - { - info.ArgumentList.Add("-Command"); - info.ArgumentList.Add($"{command}\\; {(_settings.CloseShellAfterPress ? $"Write-Host '{Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); - } - break; - } case Shell.Pwsh: - { - // Using just a ; doesn't work with wt, as it's used to create a new tab for the terminal window - // \\ must be escaped for it to work properly, or breaking it into multiple arguments - var addedCharacter = _settings.UseWindowsTerminal ? "\\" : ""; - if (_settings.UseWindowsTerminal) { - info.FileName = "wt.exe"; - info.ArgumentList.Add("pwsh"); + // Using just a ; doesn't work with wt, as it's used to create a new tab for the terminal window + // \\ must be escaped for it to work properly, or breaking it into multiple arguments + var addedCharacter = _settings.UseWindowsTerminal ? "\\" : ""; + if (_settings.UseWindowsTerminal) + { + info.FileName = "wt.exe"; + info.ArgumentList.Add("pwsh"); + } + else + { + info.FileName = "pwsh.exe"; + } + if (_settings.LeaveShellOpen) + { + info.ArgumentList.Add("-NoExit"); + } + info.ArgumentList.Add("-Command"); + info.ArgumentList.Add($"{command}{addedCharacter}; {(_settings.CloseShellAfterPress ? $"Write-Host '{Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'{addedCharacter}; [System.Console]::ReadKey(){addedCharacter}; exit" : "")}"); + break; } - else - { - info.FileName = "pwsh.exe"; - } - if (_settings.LeaveShellOpen) - { - info.ArgumentList.Add("-NoExit"); - } - info.ArgumentList.Add("-Command"); - info.ArgumentList.Add($"{command}{addedCharacter}; {(_settings.CloseShellAfterPress ? $"Write-Host '{Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); - break; - } case Shell.RunCommand: - { - var parts = command.Split(new[] { - ' ' - }, 2); - if (parts.Length == 2) - { - var filename = parts[0]; - if (ExistInPath(filename)) + var parts = command.Split(new[] { - var arguments = parts[1]; - info.FileName = filename; - info.ArgumentList.Add(arguments); + ' ' + }, 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; } - } - else - { - info.FileName = command; + + info.UseShellExecute = true; + + break; } - info.UseShellExecute = true; - - break; - } default: throw new NotImplementedException(); } From 08c8b8c09febcf1051dfc9e49f8f051b41bff646 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 5 Jun 2025 19:15:26 +0800 Subject: [PATCH 04/16] Do not show UI when shortcuts cannot be resolved --- .../Programs/ShellLinkHelper.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLinkHelper.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLinkHelper.cs index a77b2ace8..34b3a6df2 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLinkHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLinkHelper.cs @@ -8,9 +8,8 @@ using Windows.Win32.Storage.FileSystem; namespace Flow.Launcher.Plugin.Program.Programs { - class ShellLinkHelper + public class ShellLinkHelper { - // Reference : http://www.pinvoke.net/default.aspx/Interfaces.IShellLinkW [ComImport(), Guid("00021401-0000-0000-C000-000000000046")] public class ShellLink @@ -28,7 +27,9 @@ namespace Flow.Launcher.Plugin.Program.Programs const int STGM_READ = 0; ((IPersistFile)link).Load(path, STGM_READ); var hwnd = new HWND(IntPtr.Zero); - ((IShellLinkW)link).Resolve(hwnd, 0); + // Use SLR_NO_UI to avoid showing any UI during resolution, like Problem with Shortcut dialogs + // https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishelllinka-resolve + ((IShellLinkW)link).Resolve(hwnd, (uint)SLR_FLAGS.SLR_NO_UI); const int MAX_PATH = 260; Span buffer = stackalloc char[MAX_PATH]; @@ -79,6 +80,6 @@ namespace Flow.Launcher.Plugin.Program.Programs Marshal.ReleaseComObject(link); return target; - } + } } } From 1697544cb65b4d766c58f41fb2a27ef4b59c37e8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 5 Jun 2025 22:41:21 +0800 Subject: [PATCH 05/16] Add example code comments --- .../FirefoxBookmarkLoader.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 492a76c7b..f3b4c109f 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -270,6 +270,7 @@ public class FirefoxBookmarkLoader : FirefoxBookmarkLoaderBase /// /// Path to places.sqlite /// + /// private static string PlacesPath { get @@ -295,6 +296,33 @@ public class FirefoxBookmarkLoader : FirefoxBookmarkLoaderBase var indexOfDefaultProfileAttributePath = lines.IndexOf("Path=" + defaultProfileFolderName); + /* + Current profiles.ini structure example as of Firefox version 69.0.1 + + [Install736426B0AF4A39CB] + Default=Profiles/7789f565.default-release <== this is the default profile this plugin will get the bookmarks from. When opened Firefox will load the default profile + Locked=1 + + [Profile2] + Name=newblahprofile + IsRelative=0 + Path=C:\t6h2yuq8.newblahprofile <== Note this is a custom location path for the profile user can set, we need to cater for this in code. + + [Profile1] + Name=default + IsRelative=1 + Path=Profiles/cydum7q4.default + Default=1 + + [Profile0] + Name=default-release + IsRelative=1 + Path=Profiles/7789f565.default-release + + [General] + StartWithLastProfile=1 + Version=2 + */ // Seen in the example above, the IsRelative attribute is always above the Path attribute var relativeAttribute = lines[indexOfDefaultProfileAttributePath - 1]; From 79d35bba5f398562fcde4ffea6ac9f70fa5a9004 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 5 Jun 2025 22:54:34 +0800 Subject: [PATCH 06/16] Check index before returning PlacesPath --- .../FirefoxBookmarkLoader.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index f3b4c109f..acace2506 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -324,11 +324,22 @@ public class FirefoxBookmarkLoader : FirefoxBookmarkLoaderBase Version=2 */ // Seen in the example above, the IsRelative attribute is always above the Path attribute + + var relativePath = Path.Combine(defaultProfileFolderName, "places.sqlite"); + var absoluePath = Path.Combine(profileFolderPath, relativePath); + + // If the index is out of range, it means that the default profile is in a custom location or the file is malformed + // If the profile is in a custom location, we need to check + if (indexOfDefaultProfileAttributePath - 1 < 0 || + indexOfDefaultProfileAttributePath - 1 >= lines.Count) + { + return Directory.Exists(absoluePath) ? absoluePath : relativePath; + } + var relativeAttribute = lines[indexOfDefaultProfileAttributePath - 1]; return relativeAttribute == "0" // See above, the profile is located in a custom location, path is not relative, so IsRelative=0 - ? defaultProfileFolderName + @"\places.sqlite" - : Path.Combine(profileFolderPath, defaultProfileFolderName) + @"\places.sqlite"; + ? relativePath : absoluePath; } } } From 8c5e0c948f6e1cc799b912207e8bbeb92967c776 Mon Sep 17 00:00:00 2001 From: DB P Date: Fri, 6 Jun 2025 17:05:12 +0900 Subject: [PATCH 07/16] Change Tabcontrol to Expander --- .../Views/ExplorerSettings.xaml | 1370 ++++++++--------- .../Views/ExplorerSettings.xaml.cs | 49 +- 2 files changed, 698 insertions(+), 721 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index 4302e721a..eff1b4751 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -10,97 +10,13 @@ xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:viewModels="clr-namespace:Flow.Launcher.Plugin.Explorer.ViewModels" xmlns:views="clr-namespace:Flow.Launcher.Plugin.Explorer.Views" + Margin="-72 0 -19 -14" d:DataContext="{d:DesignInstance viewModels:SettingsViewModel}" d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d"> - - @@ -163,653 +79,685 @@ + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - + + + + + + + + + + + + + + + + + + -