From fe0153be088d8f82877d7ea06b46364a556c68f5 Mon Sep 17 00:00:00 2001
From: Garulf <535299+Garulf@users.noreply.github.com>
Date: Wed, 15 Dec 2021 05:21:40 -0500
Subject: [PATCH 01/79] Initial commit
---
Flow.Launcher/Flow.Launcher.csproj | 33 ++++++++++++
Flow.Launcher/ViewModel/MainViewModel.cs | 65 +++++++++++++++++++++++-
2 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index f431504c2..117dececf 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -77,6 +77,24 @@
Designer
PreserveNewest
+
+ 1
+ 1
+ eab22ac0-30c1-11cf-a7eb-0000c05bae0b
+ 0
+ tlbimp
+ false
+ true
+
+
+ 0
+ 1
+ 50a7e9b0-70ef-11d1-b75a-00a0c90564fe
+ 0
+ tlbimp
+ false
+ true
+
PreserveNewest
@@ -110,6 +128,21 @@
+
+
+ True
+ True
+ Settings.settings
+
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index abf3a1d14..cbe35e0f5 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -20,7 +20,9 @@ using Flow.Launcher.Infrastructure.Logger;
using Microsoft.VisualStudio.Threading;
using System.Threading.Channels;
using ISavable = Flow.Launcher.Plugin.ISavable;
-
+using System.Runtime.InteropServices;
+using System.Text;
+using SHDocVw;
namespace Flow.Launcher.ViewModel
{
@@ -720,6 +722,62 @@ namespace Flow.Launcher.ViewModel
OpenResultCommandModifiers = _settings.OpenResultModifiers ?? DefaultOpenResultModifiers;
}
+ private static string GetActiveExplorerPath()
+ {
+ // get the active window
+ IntPtr handle = GetForegroundWindow();
+
+ // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll
+ ShellWindows shellWindows = new SHDocVw.ShellWindows();
+
+ // loop through all windows
+ foreach (InternetExplorer window in shellWindows)
+ {
+ // match active window
+ if (window.HWND == (int)handle)
+ {
+ // Required ref: Shell32 - C:\Windows\system32\Shell32.dll
+ var shellWindow = window.Document as Shell32.IShellFolderViewDual2;
+
+ // will be null if you are in Internet Explorer for example
+ if (shellWindow != null)
+ {
+ // Item without an index returns the current object
+ var currentFolder = shellWindow.Folder.Items().Item();
+
+ // special folder - use window title
+ // for some reason on "Desktop" gives null
+ if (currentFolder == null || currentFolder.Path.StartsWith("::"))
+ {
+ // Get window title instead
+ const int nChars = 256;
+ StringBuilder Buff = new StringBuilder(nChars);
+ if (GetWindowText(handle, Buff, nChars) > 0)
+ {
+ return Buff.ToString();
+ }
+ }
+ else
+ {
+ return currentFolder.Path;
+ }
+ }
+
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ // COM Imports
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll")]
+ static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
+
public void ToggleFlowLauncher()
{
if (!MainWindowVisibilityStatus)
@@ -734,6 +792,9 @@ namespace Flow.Launcher.ViewModel
public void Show()
{
+ string _explorerPath = GetActiveExplorerPath();
+
+ ChangeQueryText($"{_explorerPath}\\>");
if (_settings.UseSound)
{
MediaPlayer media = new MediaPlayer();
@@ -749,6 +810,8 @@ namespace Flow.Launcher.ViewModel
((MainWindow)Application.Current.MainWindow).WindowAnimator();
MainWindowOpacity = 1;
+
+
}
public async void Hide()
From 79a6fda289dfa641e011588f500d98b22425b3d2 Mon Sep 17 00:00:00 2001
From: Garulf <535299+Garulf@users.noreply.github.com>
Date: Wed, 15 Dec 2021 05:24:31 -0500
Subject: [PATCH 02/79] Only insert when explorer is active
---
Flow.Launcher/ViewModel/MainViewModel.cs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index cbe35e0f5..7a48d159f 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -793,8 +793,11 @@ namespace Flow.Launcher.ViewModel
public void Show()
{
string _explorerPath = GetActiveExplorerPath();
-
- ChangeQueryText($"{_explorerPath}\\>");
+ if (_explorerPath != null)
+ {
+ ChangeQueryText($"{_explorerPath}\\>");
+ }
+
if (_settings.UseSound)
{
MediaPlayer media = new MediaPlayer();
From 1fdaec2648f14994b9b15fc86c732629796f6f13 Mon Sep 17 00:00:00 2001
From: Garulf <535299+Garulf@users.noreply.github.com>
Date: Wed, 15 Dec 2021 06:15:05 -0500
Subject: [PATCH 03/79] ChangeQuery after window is visible
---
Flow.Launcher/ViewModel/MainViewModel.cs | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 7a48d159f..b525ac342 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -731,7 +731,7 @@ namespace Flow.Launcher.ViewModel
ShellWindows shellWindows = new SHDocVw.ShellWindows();
// loop through all windows
- foreach (InternetExplorer window in shellWindows)
+ foreach (SHDocVw.InternetExplorer window in shellWindows)
{
// match active window
if (window.HWND == (int)handle)
@@ -793,10 +793,7 @@ namespace Flow.Launcher.ViewModel
public void Show()
{
string _explorerPath = GetActiveExplorerPath();
- if (_explorerPath != null)
- {
- ChangeQueryText($"{_explorerPath}\\>");
- }
+
if (_settings.UseSound)
{
@@ -813,7 +810,10 @@ namespace Flow.Launcher.ViewModel
((MainWindow)Application.Current.MainWindow).WindowAnimator();
MainWindowOpacity = 1;
-
+ if (_explorerPath != null && _explorerPath != "File Explorer")
+ {
+ ChangeQueryText($"{_explorerPath}\\>");
+ }
}
From 1109f9887e78ddcfda62f0e775893f6161344ec2 Mon Sep 17 00:00:00 2001
From: Garulf <535299+Garulf@users.noreply.github.com>
Date: Thu, 16 Dec 2021 02:03:22 -0500
Subject: [PATCH 04/79] Remove unnecessary changes
---
Flow.Launcher/Flow.Launcher.csproj | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 117dececf..9d4042700 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -128,21 +128,6 @@
-
-
- True
- True
- Settings.settings
-
-
-
-
-
- SettingsSingleFileGenerator
- Settings.Designer.cs
-
-
-
From aa5ca76b180b94680ee4f1f677581eb35bbf7424 Mon Sep 17 00:00:00 2001
From: Garulf <535299+Garulf@users.noreply.github.com>
Date: Mon, 20 Dec 2021 03:34:41 -0500
Subject: [PATCH 05/79] Check window is InternetExplorer type
---
Flow.Launcher/ViewModel/MainViewModel.cs | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index b525ac342..412af09fd 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -731,13 +731,19 @@ namespace Flow.Launcher.ViewModel
ShellWindows shellWindows = new SHDocVw.ShellWindows();
// loop through all windows
- foreach (SHDocVw.InternetExplorer window in shellWindows)
+ foreach (var window in shellWindows)
{
+ if (window is not SHDocVw.InternetExplorer)
+ {
+ continue;
+ }
+
+ var explorerWindow = (SHDocVw.InternetExplorer)window;
// match active window
- if (window.HWND == (int)handle)
+ if (explorerWindow.HWND == (int)handle)
{
// Required ref: Shell32 - C:\Windows\system32\Shell32.dll
- var shellWindow = window.Document as Shell32.IShellFolderViewDual2;
+ var shellWindow = explorerWindow.Document as Shell32.IShellFolderViewDual2;
// will be null if you are in Internet Explorer for example
if (shellWindow != null)
From c039b17d93c66717dbdaf4a14843ce19a224f5c8 Mon Sep 17 00:00:00 2001
From: stefnotch
Date: Sat, 16 Jul 2022 11:16:00 +0200
Subject: [PATCH 06/79] Refactor file explorer path getting
---
Flow.Launcher/Helper/FileExplorerHelper.cs | 70 ++++++++++++++++++++++
Flow.Launcher/ViewModel/MainViewModel.cs | 66 +-------------------
2 files changed, 72 insertions(+), 64 deletions(-)
create mode 100644 Flow.Launcher/Helper/FileExplorerHelper.cs
diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs
new file mode 100644
index 000000000..16152e830
--- /dev/null
+++ b/Flow.Launcher/Helper/FileExplorerHelper.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.IO;
+
+namespace Flow.Launcher.Helper
+{
+ public class FileExplorerHelper
+ {
+
+ ///
+ /// Gets the path of the file explorer that is currently in the foreground
+ ///
+ public static string GetActiveExplorerPath()
+ {
+ var explorerWindow = GetActiveExplorer();
+ string locationUrl = explorerWindow.LocationURL;
+ if (!string.IsNullOrEmpty(locationUrl))
+ {
+ return new Uri(locationUrl).LocalPath;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Gets the file explorer that is currently in the foreground
+ ///
+ private static SHDocVw.InternetExplorer GetActiveExplorer()
+ {
+ // get the active window
+ IntPtr handle = GetForegroundWindow();
+
+ // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll
+ var shellWindows = new SHDocVw.ShellWindows();
+
+ // loop through all windows
+ foreach (var window in shellWindows)
+ {
+ if (window is SHDocVw.InternetExplorer explorerWindow && new IntPtr(explorerWindow.HWND) == handle)
+ {
+ // we have found the desired window, now let's make sure that it is indeed a file explorer
+ // we don't want the Internet Explorer or the classic control panel
+ if (explorerWindow.Document is not Shell32.IShellFolderViewDual2)
+ {
+ return null;
+ }
+ if (Path.GetFileName(explorerWindow.FullName) != "explorer.exe")
+ {
+ return null;
+ }
+
+ return explorerWindow;
+ }
+ }
+
+ return null;
+ }
+
+ // COM Imports
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll")]
+ static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
+ }
+}
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 412af09fd..ff0c88339 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -722,68 +722,6 @@ namespace Flow.Launcher.ViewModel
OpenResultCommandModifiers = _settings.OpenResultModifiers ?? DefaultOpenResultModifiers;
}
- private static string GetActiveExplorerPath()
- {
- // get the active window
- IntPtr handle = GetForegroundWindow();
-
- // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll
- ShellWindows shellWindows = new SHDocVw.ShellWindows();
-
- // loop through all windows
- foreach (var window in shellWindows)
- {
- if (window is not SHDocVw.InternetExplorer)
- {
- continue;
- }
-
- var explorerWindow = (SHDocVw.InternetExplorer)window;
- // match active window
- if (explorerWindow.HWND == (int)handle)
- {
- // Required ref: Shell32 - C:\Windows\system32\Shell32.dll
- var shellWindow = explorerWindow.Document as Shell32.IShellFolderViewDual2;
-
- // will be null if you are in Internet Explorer for example
- if (shellWindow != null)
- {
- // Item without an index returns the current object
- var currentFolder = shellWindow.Folder.Items().Item();
-
- // special folder - use window title
- // for some reason on "Desktop" gives null
- if (currentFolder == null || currentFolder.Path.StartsWith("::"))
- {
- // Get window title instead
- const int nChars = 256;
- StringBuilder Buff = new StringBuilder(nChars);
- if (GetWindowText(handle, Buff, nChars) > 0)
- {
- return Buff.ToString();
- }
- }
- else
- {
- return currentFolder.Path;
- }
- }
-
- break;
- }
- }
-
- return null;
- }
-
- // COM Imports
-
- [DllImport("user32.dll")]
- private static extern IntPtr GetForegroundWindow();
-
- [DllImport("user32.dll")]
- static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
-
public void ToggleFlowLauncher()
{
if (!MainWindowVisibilityStatus)
@@ -798,7 +736,7 @@ namespace Flow.Launcher.ViewModel
public void Show()
{
- string _explorerPath = GetActiveExplorerPath();
+ string _explorerPath = FileExplorerHelper.GetActiveExplorerPath();
if (_settings.UseSound)
@@ -816,7 +754,7 @@ namespace Flow.Launcher.ViewModel
((MainWindow)Application.Current.MainWindow).WindowAnimator();
MainWindowOpacity = 1;
- if (_explorerPath != null && _explorerPath != "File Explorer")
+ if (_explorerPath != null)
{
ChangeQueryText($"{_explorerPath}\\>");
}
From 81bacdb9a72e5482788d2f90933e46659fd4ce42 Mon Sep 17 00:00:00 2001
From: stefnotch
Date: Sat, 16 Jul 2022 11:20:36 +0200
Subject: [PATCH 07/79] Remove unused function
---
Flow.Launcher/Helper/FileExplorerHelper.cs | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs
index 16152e830..3b24b7414 100644
--- a/Flow.Launcher/Helper/FileExplorerHelper.cs
+++ b/Flow.Launcher/Helper/FileExplorerHelper.cs
@@ -63,8 +63,5 @@ namespace Flow.Launcher.Helper
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
-
- [DllImport("user32.dll")]
- static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
}
}
From ab306d90cc1ef0187b3227c9174d303e846c38fa Mon Sep 17 00:00:00 2001
From: stefnotch
Date: Sat, 16 Jul 2022 11:22:31 +0200
Subject: [PATCH 08/79] Remove unused imports
---
Flow.Launcher/ViewModel/MainViewModel.cs | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index ff0c88339..d785249a6 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -20,9 +20,6 @@ using Flow.Launcher.Infrastructure.Logger;
using Microsoft.VisualStudio.Threading;
using System.Threading.Channels;
using ISavable = Flow.Launcher.Plugin.ISavable;
-using System.Runtime.InteropServices;
-using System.Text;
-using SHDocVw;
namespace Flow.Launcher.ViewModel
{
From 1606908d28484c1cc63410be0bbd2ef499730e25 Mon Sep 17 00:00:00 2001
From: stefnotch
Date: Mon, 8 Aug 2022 19:07:18 +0200
Subject: [PATCH 09/79] Move to dynamic
---
Flow.Launcher/Flow.Launcher.csproj | 18 ------------
Flow.Launcher/Helper/FileExplorerHelper.cs | 34 +++++++++-------------
2 files changed, 14 insertions(+), 38 deletions(-)
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 9d4042700..f431504c2 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -77,24 +77,6 @@
Designer
PreserveNewest
-
- 1
- 1
- eab22ac0-30c1-11cf-a7eb-0000c05bae0b
- 0
- tlbimp
- false
- true
-
-
- 0
- 1
- 50a7e9b0-70ef-11d1-b75a-00a0c90564fe
- 0
- tlbimp
- false
- true
-
PreserveNewest
diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs
index 3b24b7414..22c3de63f 100644
--- a/Flow.Launcher/Helper/FileExplorerHelper.cs
+++ b/Flow.Launcher/Helper/FileExplorerHelper.cs
@@ -14,7 +14,7 @@ namespace Flow.Launcher.Helper
public static string GetActiveExplorerPath()
{
var explorerWindow = GetActiveExplorer();
- string locationUrl = explorerWindow.LocationURL;
+ string locationUrl = explorerWindow?.LocationURL;
if (!string.IsNullOrEmpty(locationUrl))
{
return new Uri(locationUrl).LocalPath;
@@ -28,31 +28,25 @@ namespace Flow.Launcher.Helper
///
/// Gets the file explorer that is currently in the foreground
///
- private static SHDocVw.InternetExplorer GetActiveExplorer()
+ private static dynamic GetActiveExplorer()
{
// get the active window
IntPtr handle = GetForegroundWindow();
- // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll
- var shellWindows = new SHDocVw.ShellWindows();
-
- // loop through all windows
- foreach (var window in shellWindows)
+ Type type = Type.GetTypeFromProgID("Shell.Application");
+ if (type == null) return null;
+ dynamic shell = Activator.CreateInstance(type);
+ var openWindows = shell.Windows();
+ for (int i = 0; i < openWindows.Count; i++)
{
- if (window is SHDocVw.InternetExplorer explorerWindow && new IntPtr(explorerWindow.HWND) == handle)
- {
- // we have found the desired window, now let's make sure that it is indeed a file explorer
- // we don't want the Internet Explorer or the classic control panel
- if (explorerWindow.Document is not Shell32.IShellFolderViewDual2)
- {
- return null;
- }
- if (Path.GetFileName(explorerWindow.FullName) != "explorer.exe")
- {
- return null;
- }
+ var window = openWindows.Item(i);
+ if (window == null) continue;
- return explorerWindow;
+ // find the desired window and make sure that it is indeed a file explorer
+ // we don't want the Internet Explorer or the classic control panel
+ if (Path.GetFileName((string)window.FullName) == "explorer.exe" && new IntPtr(window.HWND) == handle)
+ {
+ return window;
}
}
From 0a062c310a1386d9e7c9bbe4ad59e3927981ea96 Mon Sep 17 00:00:00 2001
From: stefnotch
Date: Mon, 8 Aug 2022 19:19:05 +0200
Subject: [PATCH 10/79] Fix querying of explorer window
---
Flow.Launcher/Helper/FileExplorerHelper.cs | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs
index 22c3de63f..c6d50f514 100644
--- a/Flow.Launcher/Helper/FileExplorerHelper.cs
+++ b/Flow.Launcher/Helper/FileExplorerHelper.cs
@@ -44,7 +44,8 @@ namespace Flow.Launcher.Helper
// find the desired window and make sure that it is indeed a file explorer
// we don't want the Internet Explorer or the classic control panel
- if (Path.GetFileName((string)window.FullName) == "explorer.exe" && new IntPtr(window.HWND) == handle)
+ // ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE"
+ if (Path.GetFileName((string)window.FullName).ToLower() == "explorer.exe" && new IntPtr(window.HWND) == handle)
{
return window;
}
@@ -53,8 +54,6 @@ namespace Flow.Launcher.Helper
return null;
}
- // COM Imports
-
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
}
From 55dee4f471641651583208f4ffbdc4b07299a4ab Mon Sep 17 00:00:00 2001
From: Hongtao Zhang
Date: Tue, 3 Jan 2023 23:05:35 -0500
Subject: [PATCH 11/79] Use the explorer window with the lowest z-index to
allow active explorer path be a built-in shortcut
---
.../FileExplorerHelper.cs | 89 +++++++++++++++++++
.../UserSettings/Settings.cs | 6 +-
Flow.Launcher/Helper/FileExplorerHelper.cs | 60 -------------
Flow.Launcher/Languages/en.xaml | 1 +
4 files changed, 94 insertions(+), 62 deletions(-)
create mode 100644 Flow.Launcher.Infrastructure/FileExplorerHelper.cs
delete mode 100644 Flow.Launcher/Helper/FileExplorerHelper.cs
diff --git a/Flow.Launcher.Infrastructure/FileExplorerHelper.cs b/Flow.Launcher.Infrastructure/FileExplorerHelper.cs
new file mode 100644
index 000000000..a3b1bd6b7
--- /dev/null
+++ b/Flow.Launcher.Infrastructure/FileExplorerHelper.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+namespace Flow.Launcher.Infrastructure
+{
+ public static class FileExplorerHelper
+ {
+ ///
+ /// Gets the path of the file explorer that is currently in the foreground
+ ///
+ public static string GetActiveExplorerPath()
+ {
+ var explorerWindow = GetActiveExplorer();
+ string locationUrl = explorerWindow?.LocationURL;
+ return !string.IsNullOrEmpty(locationUrl) ? new Uri(locationUrl).LocalPath : null;
+ }
+
+ ///
+ /// Gets the file explorer that is currently in the foreground
+ ///
+ private static dynamic GetActiveExplorer()
+ {
+ Type type = Type.GetTypeFromProgID("Shell.Application");
+ if (type == null) return null;
+ dynamic shell = Activator.CreateInstance(type);
+ if (shell == null)
+ {
+ return null;
+ }
+
+ var explorerWindows = new List();
+ var openWindows = shell.Windows();
+ for (int i = 0; i < openWindows.Count; i++)
+ {
+ var window = openWindows.Item(i);
+ if (window == null) continue;
+
+ // find the desired window and make sure that it is indeed a file explorer
+ // we don't want the Internet Explorer or the classic control panel
+ // ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE"
+ if (Path.GetFileName((string)window.FullName)?.ToLower() == "explorer.exe")
+ {
+ explorerWindows.Add(window);
+ }
+ }
+
+ if (explorerWindows.Count == 0) return null;
+
+ var zOrders = GetZOrder(explorerWindows);
+
+ return explorerWindows.Zip(zOrders).MinBy(x => x.Second).First;
+ }
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
+
+ private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
+
+ ///
+ /// Gets the z-order for one or more windows atomically with respect to each other. In Windows, smaller z-order is higher. If the window is not top level, the z order is returned as -1.
+ ///
+ private static IEnumerable GetZOrder(List hWnds)
+ {
+ var z = new int[hWnds.Count];
+ for (var i = 0; i < hWnds.Count; i++) z[i] = -1;
+
+ var index = 0;
+ var numRemaining = hWnds.Count;
+ EnumWindows((wnd, _) =>
+ {
+ var searchIndex = hWnds.FindIndex(x => x.HWND == wnd.ToInt32());
+ if (searchIndex != -1)
+ {
+ z[searchIndex] = index;
+ numRemaining--;
+ if (numRemaining == 0) return false;
+ }
+ index++;
+ return true;
+ }, IntPtr.Zero);
+
+ return z;
+ }
+ }
+}
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index a184520d0..753334e23 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -192,8 +192,10 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public ObservableCollection CustomShortcuts { get; set; } = new ObservableCollection();
[JsonIgnore]
- public ObservableCollection BuiltinShortcuts { get; set; } = new ObservableCollection() {
- new BuiltinShortcutModel("{clipboard}", "shortcut_clipboard_description", Clipboard.GetText)
+ public ObservableCollection BuiltinShortcuts { get; set; } = new()
+ {
+ new BuiltinShortcutModel("{clipboard}", "shortcut_clipboard_description", Clipboard.GetText),
+ new BuiltinShortcutModel("{active_explorer_path}", "shortcut_active_explorer_path", FileExplorerHelper.GetActiveExplorerPath)
};
public bool DontPromptUpdateMsg { get; set; }
diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs
deleted file mode 100644
index c6d50f514..000000000
--- a/Flow.Launcher/Helper/FileExplorerHelper.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using System;
-using System.Text;
-using System.Runtime.InteropServices;
-using System.IO;
-
-namespace Flow.Launcher.Helper
-{
- public class FileExplorerHelper
- {
-
- ///
- /// Gets the path of the file explorer that is currently in the foreground
- ///
- public static string GetActiveExplorerPath()
- {
- var explorerWindow = GetActiveExplorer();
- string locationUrl = explorerWindow?.LocationURL;
- if (!string.IsNullOrEmpty(locationUrl))
- {
- return new Uri(locationUrl).LocalPath;
- }
- else
- {
- return null;
- }
- }
-
- ///
- /// Gets the file explorer that is currently in the foreground
- ///
- private static dynamic GetActiveExplorer()
- {
- // get the active window
- IntPtr handle = GetForegroundWindow();
-
- Type type = Type.GetTypeFromProgID("Shell.Application");
- if (type == null) return null;
- dynamic shell = Activator.CreateInstance(type);
- var openWindows = shell.Windows();
- for (int i = 0; i < openWindows.Count; i++)
- {
- var window = openWindows.Item(i);
- if (window == null) continue;
-
- // find the desired window and make sure that it is indeed a file explorer
- // we don't want the Internet Explorer or the classic control panel
- // ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE"
- if (Path.GetFileName((string)window.FullName).ToLower() == "explorer.exe" && new IntPtr(window.HWND) == handle)
- {
- return window;
- }
- }
-
- return null;
- }
-
- [DllImport("user32.dll")]
- private static extern IntPtr GetForegroundWindow();
- }
-}
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index b192617cb..49c603dc8 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -176,6 +176,7 @@
Are you sure you want to delete {0} plugin hotkey?
Are you sure you want to delete shortcut: {0} with expansion {1}?
Get text from clipboard.
+ Get path from active explorer.
Query window shadow effect
Shadow effect has a substantial usage of GPU. Not recommended if your computer performance is limited.
Window Width Size
From f5d3acbe233bc9603a1b36f129148c400cf2fd3d Mon Sep 17 00:00:00 2001
From: Hongtao Zhang
Date: Tue, 3 Jan 2023 23:23:56 -0500
Subject: [PATCH 12/79] Catch General Exception when checking update, and use
PeriodicTimer to avoid error to crash the main thread
---
Flow.Launcher.Core/Updater.cs | 10 +++++++---
Flow.Launcher/App.xaml.cs | 20 +++++++++-----------
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs
index 91de8298c..3f64b273e 100644
--- a/Flow.Launcher.Core/Updater.cs
+++ b/Flow.Launcher.Core/Updater.cs
@@ -33,7 +33,7 @@ namespace Flow.Launcher.Core
public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true)
{
- await UpdateLock.WaitAsync();
+ await UpdateLock.WaitAsync().ConfigureAwait(false);
try
{
if (!silentUpdate)
@@ -88,9 +88,13 @@ namespace Flow.Launcher.Core
UpdateManager.RestartApp(Constant.ApplicationFileName);
}
}
- catch (Exception e) when (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException)
+ catch (Exception e)
{
- Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e);
+ if ((e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException))
+ Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e);
+ else
+ Log.Exception($"|Updater.UpdateApp|Error Occurred", e);
+
if (!silentUpdate)
api.ShowMsg(api.GetTranslation("update_flowlauncher_fail"),
api.GetTranslation("update_flowlauncher_check_connection"));
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index 43fa0eddb..9df936e76 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
@@ -84,7 +85,7 @@ namespace Flow.Launcher
Current.MainWindow = window;
Current.MainWindow.Title = Constant.FlowLauncher;
-
+
HotKeyMapper.Initialize(_mainVM);
// happlebao todo temp fix for instance code logic
@@ -130,20 +131,17 @@ namespace Flow.Launcher
//[Conditional("RELEASE")]
private void AutoUpdates()
{
- Task.Run(async () =>
+ _ = Task.Run(async () =>
{
if (_settings.AutoUpdates)
{
- // check udpate every 5 hours
- var timer = new Timer(1000 * 60 * 60 * 5);
- timer.Elapsed += async (s, e) =>
- {
- await _updater.UpdateAppAsync(API);
- };
- timer.Start();
-
- // check updates on startup
+ // check update every 5 hours
+ var timer = new PeriodicTimer(TimeSpan.FromHours(5));
await _updater.UpdateAppAsync(API);
+
+ while (await timer.WaitForNextTickAsync())
+ // check updates on startup
+ await _updater.UpdateAppAsync(API);
}
});
}
From c2137011e8ae13781207b67ddbdc73e8c09bebc0 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 7 Jan 2023 22:15:57 +1100
Subject: [PATCH 13/79] Update comment
---
Flow.Launcher/App.xaml.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index 9df936e76..4ae754fcd 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -88,7 +88,7 @@ namespace Flow.Launcher
HotKeyMapper.Initialize(_mainVM);
- // happlebao todo temp fix for instance code logic
+ // todo temp fix for instance code logic
// load plugin before change language, because plugin language also needs be changed
InternationalizationManager.Instance.Settings = _settings;
InternationalizationManager.Instance.ChangeLanguage(_settings.Language);
From dfe2c01fb5745381561724e417899c1686e53196 Mon Sep 17 00:00:00 2001
From: Hongtao Zhang
Date: Sat, 7 Jan 2023 09:14:18 -0600
Subject: [PATCH 14/79] fix spelling
---
Flow.Launcher/App.xaml.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index 4ae754fcd..1d398276d 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -92,7 +92,7 @@ namespace Flow.Launcher
// load plugin before change language, because plugin language also needs be changed
InternationalizationManager.Instance.Settings = _settings;
InternationalizationManager.Instance.ChangeLanguage(_settings.Language);
- // main windows needs initialized before theme change because of blur settigns
+ // main windows needs initialized before theme change because of blur settings
ThemeManager.Instance.Settings = _settings;
ThemeManager.Instance.ChangeTheme(_settings.Theme);
From a92ebf5756ba6f937189f3c30becbd88e3104040 Mon Sep 17 00:00:00 2001
From: Hongtao Zhang
Date: Sun, 8 Jan 2023 16:31:37 -0600
Subject: [PATCH 15/79] Dynamic Height and Dynamic Icon Size
---
.../DiameterToCenterPointConverter.cs | 25 +++
.../Converters/IconRadiusConverter.cs | 27 +++
Flow.Launcher/ResultListBox.xaml | 155 +++++++++++-------
Flow.Launcher/Themes/Base.xaml | 8 +
Flow.Launcher/ViewModel/ResultsViewModel.cs | 2 +-
5 files changed, 156 insertions(+), 61 deletions(-)
create mode 100644 Flow.Launcher/Converters/DiameterToCenterPointConverter.cs
create mode 100644 Flow.Launcher/Converters/IconRadiusConverter.cs
diff --git a/Flow.Launcher/Converters/DiameterToCenterPointConverter.cs b/Flow.Launcher/Converters/DiameterToCenterPointConverter.cs
new file mode 100644
index 000000000..e81bb2507
--- /dev/null
+++ b/Flow.Launcher/Converters/DiameterToCenterPointConverter.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace Flow.Launcher.Converters
+{
+ public class DiameterToCenterPointConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is double d)
+ {
+ return new Point(d / 2, d / 2);
+ }
+
+ return new Point(0, 0);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/Flow.Launcher/Converters/IconRadiusConverter.cs b/Flow.Launcher/Converters/IconRadiusConverter.cs
new file mode 100644
index 000000000..51129cfb8
--- /dev/null
+++ b/Flow.Launcher/Converters/IconRadiusConverter.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+using Windows.Devices.PointOfService;
+
+namespace Flow.Launcher.Converters
+{
+ public class IconRadiusConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (values.Length != 2)
+ throw new ArgumentException("IconRadiusConverter must have 2 parameters");
+
+ return values[1] switch
+ {
+ true => (double)values[0] / 2,
+ false => (double)values[0],
+ _ => throw new ArgumentException("The second argument should be boolean", nameof(values))
+ };
+ }
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 8f3238303..b2ab4a287 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -1,5 +1,4 @@
-
+
+
+
+
@@ -205,24 +231,28 @@
-
+
\ No newline at end of file
diff --git a/Flow.Launcher/Themes/Base.xaml b/Flow.Launcher/Themes/Base.xaml
index 0b4460d46..7e2e1fadd 100644
--- a/Flow.Launcher/Themes/Base.xaml
+++ b/Flow.Launcher/Themes/Base.xaml
@@ -8,6 +8,8 @@
0
+ 52
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
@@ -231,28 +217,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #d6d4d7
+
+
+
+
+
+
+
+
+
+
+
+ 6
+ 4 0 4 0
+ 0 0 0 4
+
+
+
+
+
+
+
+
From f109fb8a3c3386337b948e5a3aca0a842b8ff42a Mon Sep 17 00:00:00 2001
From: Hongtao Zhang
Date: Sun, 8 Jan 2023 20:03:22 -0600
Subject: [PATCH 18/79] Notify MaxResultsToShow to trigger max height change
when changing theme
---
.../UserSettings/Settings.cs | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index 753334e23..55c0d9973 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -13,6 +13,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public class Settings : BaseModel
{
private string language = "en";
+ private string _theme = Constant.DefaultTheme;
public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}";
public string OpenResultModifiers { get; set; } = KeyConstant.Alt;
public string ColorScheme { get; set; } = "System";
@@ -29,7 +30,18 @@ namespace Flow.Launcher.Infrastructure.UserSettings
OnPropertyChanged();
}
}
- public string Theme { get; set; } = Constant.DefaultTheme;
+ public string Theme
+ {
+ get => _theme;
+ set
+ {
+ if (value == _theme)
+ return;
+ _theme = value;
+ OnPropertyChanged();
+ OnPropertyChanged(nameof(MaxResultsToShow));
+ }
+ }
public bool UseDropShadowEffect { get; set; } = false;
public string QueryBoxFont { get; set; } = FontFamily.GenericSansSerif.Name;
public string QueryBoxFontStyle { get; set; }
From 1defb6a4172e9fd6dd0d8b0cb6b4fc3896eaa312 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Mon, 9 Jan 2023 18:02:50 +0800
Subject: [PATCH 19/79] Refactor HotkeyModel
---
.../Hotkey/HotkeyModel.cs | 66 ++++++++++++++-----
1 file changed, 51 insertions(+), 15 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Hotkey/HotkeyModel.cs b/Flow.Launcher.Infrastructure/Hotkey/HotkeyModel.cs
index 5bd97714c..e4a020cb7 100644
--- a/Flow.Launcher.Infrastructure/Hotkey/HotkeyModel.cs
+++ b/Flow.Launcher.Infrastructure/Hotkey/HotkeyModel.cs
@@ -11,10 +11,21 @@ namespace Flow.Launcher.Infrastructure.Hotkey
public bool Shift { get; set; }
public bool Win { get; set; }
public bool Ctrl { get; set; }
- public Key CharKey { get; set; }
+ private Key charKey = Key.None;
+ public Key CharKey
+ {
+ get => charKey;
+ set
+ {
+ if (ValidateHotkey(value))
+ {
+ charKey = value;
+ }
+ }
+ }
- Dictionary specialSymbolDictionary = new Dictionary
+ private static readonly Dictionary specialSymbolDictionary = new Dictionary
{
{Key.Space, "Space"},
{Key.Oem3, "~"}
@@ -86,7 +97,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey
Ctrl = true;
keys.Remove("Ctrl");
}
- if (keys.Count > 0)
+ if (keys.Count == 1)
{
string charKey = keys[0];
KeyValuePair? specialSymbolPair = specialSymbolDictionary.FirstOrDefault(pair => pair.Value == charKey);
@@ -110,36 +121,61 @@ namespace Flow.Launcher.Infrastructure.Hotkey
public override string ToString()
{
- string text = string.Empty;
+ List keys = new List();
if (Ctrl)
{
- text += "Ctrl + ";
+ keys.Add("Ctrl");
}
if (Alt)
{
- text += "Alt + ";
+ keys.Add("Alt");
}
if (Shift)
{
- text += "Shift + ";
+ keys.Add("Shift");
}
if (Win)
{
- text += "Win + ";
+ keys.Add("Win");
}
if (CharKey != Key.None)
{
- text += specialSymbolDictionary.ContainsKey(CharKey)
+ keys.Add(specialSymbolDictionary.ContainsKey(CharKey)
? specialSymbolDictionary[CharKey]
- : CharKey.ToString();
- }
- else if (!string.IsNullOrEmpty(text))
- {
- text = text.Remove(text.Length - 3);
+ : CharKey.ToString());
}
+ return string.Join(" + ", keys);
+ }
- return text;
+ private static bool ValidateHotkey(Key key)
+ {
+ HashSet invalidKeys = new()
+ {
+ Key.LeftAlt, Key.RightAlt,
+ Key.LeftCtrl, Key.RightCtrl,
+ Key.LeftShift, Key.RightShift,
+ Key.LWin, Key.RWin,
+ };
+
+ return !invalidKeys.Contains(key);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is HotkeyModel other)
+ {
+ return ModifierKeys == other.ModifierKeys && CharKey == other.charKey;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return this.ToString().GetHashCode();
}
}
}
From 10fa2f7beb8d01a35990ba6c156db2c263e11acd Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Mon, 9 Jan 2023 21:50:29 +0800
Subject: [PATCH 20/79] Validate hotkey
---
Flow.Launcher/HotkeyControl.xaml.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs
index d746c8fd2..ffa73da15 100644
--- a/Flow.Launcher/HotkeyControl.xaml.cs
+++ b/Flow.Launcher/HotkeyControl.xaml.cs
@@ -9,7 +9,6 @@ using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Plugin;
using System.Threading;
-using System.Windows.Interop;
namespace Flow.Launcher
{
@@ -79,7 +78,7 @@ namespace Flow.Launcher
if (triggerValidate)
{
- CurrentHotkeyAvailable = CheckHotkeyAvailability();
+ CurrentHotkeyAvailable = CurrentHotkey.CharKey != Key.None && CheckHotkeyAvailability();
if (!CurrentHotkeyAvailable)
{
tbMsg.Foreground = new SolidColorBrush(Colors.Red);
From ff79651fb2bd1b7ddde8345d05da92938434e9aa Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Mon, 9 Jan 2023 22:08:27 +0800
Subject: [PATCH 21/79] Use Equals() for comparison
---
Flow.Launcher/HotkeyControl.xaml.cs | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs
index ffa73da15..7d2da76da 100644
--- a/Flow.Launcher/HotkeyControl.xaml.cs
+++ b/Flow.Launcher/HotkeyControl.xaml.cs
@@ -54,9 +54,7 @@ namespace Flow.Launcher
specialKeyState.CtrlPressed,
key);
- var hotkeyString = hotkeyModel.ToString();
-
- if (hotkeyString == tbHotkey.Text)
+ if (hotkeyModel.Equals(CurrentHotkey))
{
return;
}
From cd056f6355d945dd367807f594c7e59b1041a14d Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Mon, 9 Jan 2023 22:09:39 +0800
Subject: [PATCH 22/79] Use overloaded version
---
Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs
index 4f8d65378..e89a7dd03 100644
--- a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs
+++ b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs
@@ -27,7 +27,7 @@ namespace Flow.Launcher.Resources.Pages
tbMsgTextOriginal = HotkeyControl.tbMsg.Text;
tbMsgForegroundColorOriginal = HotkeyControl.tbMsg.Foreground;
- HotkeyControl.SetHotkeyAsync(new Infrastructure.Hotkey.HotkeyModel(Settings.Hotkey), false);
+ HotkeyControl.SetHotkeyAsync(Settings.Hotkey, false);
}
private void HotkeyControl_OnGotFocus(object sender, RoutedEventArgs args)
{
@@ -49,4 +49,4 @@ namespace Flow.Launcher.Resources.Pages
HotkeyControl.tbMsg.Foreground = tbMsgForegroundColorOriginal;
}
}
-}
\ No newline at end of file
+}
From 5e0adbaf36222b31eaa7fbe102cfdfdb522f62a2 Mon Sep 17 00:00:00 2001
From: Kevin Zhang <45326534+taooceros@users.noreply.github.com>
Date: Mon, 9 Jan 2023 09:03:10 -0600
Subject: [PATCH 23/79] Remove await Task.Run for IconDelegate (#1704)
Let's trust plugin developer when they use that for icon
---
Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 151bb580c..3f204c16c 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -188,7 +188,7 @@ namespace Flow.Launcher.ViewModel
{
try
{
- var image = await Task.Run(() => icon()).ConfigureAwait(false);
+ var image = icon();
return image;
}
catch (Exception e)
From 4a0891cac7e603fc4cf4e1b633bb94cbbf521eb7 Mon Sep 17 00:00:00 2001
From: Hongtao Zhang
Date: Mon, 9 Jan 2023 09:39:50 -0600
Subject: [PATCH 24/79] revise theme structure to achieve the property update
---
Flow.Launcher.Core/Resource/Theme.cs | 30 ++++++++++++-------
.../ViewModel/SettingWindowViewModel.cs | 1 -
2 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs
index 872c4543e..20180c3d0 100644
--- a/Flow.Launcher.Core/Resource/Theme.cs
+++ b/Flow.Launcher.Core/Resource/Theme.cs
@@ -82,13 +82,14 @@ namespace Flow.Launcher.Core.Resource
{
if (string.IsNullOrEmpty(path))
throw new DirectoryNotFoundException("Theme path can't be found <{path}>");
-
- Settings.Theme = theme;
-
+
// reload all resources even if the theme itself hasn't changed in order to pickup changes
// to things like fonts
- UpdateResourceDictionary(GetResourceDictionary());
+ UpdateResourceDictionary(GetResourceDictionary(theme));
+
+ Settings.Theme = theme;
+
//always allow re-loading default theme, in case of failure of switching to a new theme from default theme
if (_oldTheme != theme || theme == defaultTheme)
{
@@ -134,9 +135,9 @@ namespace Flow.Launcher.Core.Resource
_oldResource = dictionaryToUpdate;
}
- private ResourceDictionary CurrentThemeResourceDictionary()
+ private ResourceDictionary GetThemeResourceDictionary(string theme)
{
- var uri = GetThemePath(Settings.Theme);
+ var uri = GetThemePath(theme);
var dict = new ResourceDictionary
{
Source = new Uri(uri, UriKind.Absolute)
@@ -145,10 +146,12 @@ namespace Flow.Launcher.Core.Resource
return dict;
}
- public ResourceDictionary GetResourceDictionary()
+ private ResourceDictionary CurrentThemeResourceDictionary() => GetThemeResourceDictionary(Settings.Theme);
+
+ public ResourceDictionary GetResourceDictionary(string theme)
{
- var dict = CurrentThemeResourceDictionary();
-
+ var dict = GetThemeResourceDictionary(theme);
+
if (dict["QueryBoxStyle"] is Style queryBoxStyle &&
dict["QuerySuggestionBoxStyle"] is Style querySuggestionBoxStyle)
{
@@ -200,6 +203,11 @@ namespace Flow.Launcher.Core.Resource
return dict;
}
+ private ResourceDictionary GetCurrentResourceDictionary( )
+ {
+ return GetResourceDictionary(Settings.Theme);
+ }
+
public List LoadAvailableThemes()
{
List themes = new List();
@@ -229,7 +237,7 @@ namespace Flow.Launcher.Core.Resource
public void AddDropShadowEffectToCurrentTheme()
{
- var dict = GetResourceDictionary();
+ var dict = GetCurrentResourceDictionary();
var windowBorderStyle = dict["WindowBorderStyle"] as Style;
@@ -273,7 +281,7 @@ namespace Flow.Launcher.Core.Resource
public void RemoveDropShadowEffectFromCurrentTheme()
{
- var dict = CurrentThemeResourceDictionary();
+ var dict = GetCurrentResourceDictionary();
var windowBorderStyle = dict["WindowBorderStyle"] as Style;
var effectSetter = windowBorderStyle.Setters.FirstOrDefault(setterBase => setterBase is Setter setter && setter.Property == Border.EffectProperty) as Setter;
diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
index 0305b70e1..b4d2cbfe9 100644
--- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
+++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
@@ -407,7 +407,6 @@ namespace Flow.Launcher.ViewModel
get { return Settings.Theme; }
set
{
- Settings.Theme = value;
ThemeManager.Instance.ChangeTheme(value);
if (ThemeManager.Instance.BlurEnabled && Settings.UseDropShadowEffect)
From 48d319387690a6e1c7729141cb33ed9ab8ef47e5 Mon Sep 17 00:00:00 2001
From: Hongtao Zhang
Date: Mon, 9 Jan 2023 09:56:48 -0600
Subject: [PATCH 25/79] Fix spelling
---
.github/actions/spelling/expect.txt | 22 +++++++++++++++++++
Flow.Launcher.Core/Resource/Theme.cs | 21 ++++++++----------
.../UserSettings/Settings.cs | 2 +-
Flow.Launcher/MainWindow.xaml.cs | 2 +-
Flow.Launcher/ResultListBox.xaml | 2 +-
Flow.Launcher/SettingWindow.xaml | 2 +-
Flow.Launcher/Themes/Base.xaml | 8 +++----
Flow.Launcher/Themes/Dracula.xaml | 2 +-
Flow.Launcher/Themes/Win11Light.xaml | 2 +-
Flow.Launcher/Themes/Win11System.xaml | 2 +-
Flow.Launcher/ViewModel/MainViewModel.cs | 10 ++++-----
Flow.Launcher/ViewModel/ResultsViewModel.cs | 10 ++++-----
.../ViewModel/SettingWindowViewModel.cs | 20 +++++++----------
13 files changed, 60 insertions(+), 45 deletions(-)
diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt
index a91287cc0..04042a3a9 100644
--- a/.github/actions/spelling/expect.txt
+++ b/.github/actions/spelling/expect.txt
@@ -62,3 +62,25 @@ TobiasSekan
Img
img
resx
+directx
+mvvm
+dlg
+ddd
+dddd
+clearlogfolder
+ACCENT_ENABLE_TRANSPARENTGRADIENT
+ACCENT_ENABLE_BLURBEHIND
+WCA_ACCENT_POLICY
+HGlobal
+dopusrt
+firefox
+msedge
+svgc
+ime
+zindex
+txb
+btn
+otf
+searchplugin
+Noresult
+wpftk
\ No newline at end of file
diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs
index 20180c3d0..96338cf6a 100644
--- a/Flow.Launcher.Core/Resource/Theme.cs
+++ b/Flow.Launcher.Core/Resource/Theme.cs
@@ -36,7 +36,7 @@ namespace Flow.Launcher.Core.Resource
{
_themeDirectories.Add(DirectoryPath);
_themeDirectories.Add(UserDirectoryPath);
- MakesureThemeDirectoriesExist();
+ MakeSureThemeDirectoriesExist();
var dicts = Application.Current.Resources.MergedDictionaries;
_oldResource = dicts.First(d =>
@@ -55,20 +55,17 @@ namespace Flow.Launcher.Core.Resource
_oldTheme = Path.GetFileNameWithoutExtension(_oldResource.Source.AbsolutePath);
}
- private void MakesureThemeDirectoriesExist()
+ private void MakeSureThemeDirectoriesExist()
{
- foreach (string dir in _themeDirectories)
+ foreach (var dir in _themeDirectories.Where(dir => !Directory.Exists(dir)))
{
- if (!Directory.Exists(dir))
+ try
{
- try
- {
- Directory.CreateDirectory(dir);
- }
- catch (Exception e)
- {
- Log.Exception($"|Theme.MakesureThemeDirectoriesExist|Exception when create directory <{dir}>", e);
- }
+ Directory.CreateDirectory(dir);
+ }
+ catch (Exception e)
+ {
+ Log.Exception($"|Theme.MakesureThemeDirectoriesExist|Exception when create directory <{dir}>", e);
}
}
}
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index 55c0d9973..bfd7e4b87 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -226,7 +226,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
}
}
public bool LeaveCmdOpen { get; set; }
- public bool HideWhenDeactive { get; set; } = true;
+ public bool HideWhenDeactivated { get; set; } = true;
public SearchWindowPositions SearchWindowPosition { get; set; } = SearchWindowPositions.MouseScreenCenter;
public bool IgnoreHotkeysOnFullscreen { get; set; }
diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs
index b2d842022..550648b24 100644
--- a/Flow.Launcher/MainWindow.xaml.cs
+++ b/Flow.Launcher/MainWindow.xaml.cs
@@ -485,7 +485,7 @@ namespace Flow.Launcher
if (_settings.UseAnimation)
await Task.Delay(100);
- if (_settings.HideWhenDeactive)
+ if (_settings.HideWhenDeactivated)
{
_viewModel.Hide();
}
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index dd3fb63ec..ba4c9e9a4 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -27,7 +27,7 @@
Style="{DynamicResource BaseListboxStyle}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Standard"
- Visibility="{Binding Visbility}"
+ Visibility="{Binding Visibility}"
mc:Ignorable="d">
diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml
index d26680edd..daf8ec608 100644
--- a/Flow.Launcher/SettingWindow.xaml
+++ b/Flow.Launcher/SettingWindow.xaml
@@ -673,7 +673,7 @@
diff --git a/Flow.Launcher/Themes/Base.xaml b/Flow.Launcher/Themes/Base.xaml
index 08a1d5add..84b979194 100644
--- a/Flow.Launcher/Themes/Base.xaml
+++ b/Flow.Launcher/Themes/Base.xaml
@@ -6,7 +6,7 @@
0
0
0
-
+
52
@@ -307,7 +307,7 @@
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
-
+
-
@@ -509,7 +509,7 @@
+
+
+
F1 M12000,12000z M0,0z M10354,10962C10326,10951 10279,10927 10249,10907 10216,10886 9476,10153 8370,9046 7366,8042 6541,7220 6536,7220 6532,7220 6498,7242 6461,7268 6213,7447 5883,7619 5592,7721 5194,7860 4802,7919 4360,7906 3612,7886 2953,7647 2340,7174 2131,7013 1832,6699 1664,6465 1394,6088 1188,5618 1097,5170 1044,4909 1030,4764 1030,4470 1030,4130 1056,3914 1135,3609 1263,3110 1511,2633 1850,2235 1936,2134 2162,1911 2260,1829 2781,1395 3422,1120 4090,1045 4271,1025 4667,1025 4848,1045 5505,1120 6100,1368 6630,1789 6774,1903 7081,2215 7186,2355 7362,2588 7467,2759 7579,2990 7802,3455 7911,3937 7911,4460 7911,4854 7861,5165 7737,5542 7684,5702 7675,5724 7602,5885 7517,6071 7390,6292 7270,6460 7242,6499 7220,6533 7220,6538 7220,6542 8046,7371 9055,8380 10441,9766 10898,10229 10924,10274 10945,10308 10966,10364 10976,10408 10990,10472 10991,10493 10980,10554 10952,10717 10840,10865 10690,10937 10621,10971 10607,10974 10510,10977 10425,10980 10395,10977 10354,10962z M4685,7050C5214,7001 5694,6809 6100,6484 6209,6396 6396,6209 6484,6100 7151,5267 7246,4110 6721,3190 6369,2571 5798,2137 5100,1956 4706,1855 4222,1855 3830,1957 3448,2056 3140,2210 2838,2453 2337,2855 2010,3427 1908,4080 1877,4274 1877,4656 1908,4850 1948,5105 2028,5370 2133,5590 2459,6272 3077,6782 3810,6973 3967,7014 4085,7034 4290,7053 4371,7061 4583,7059 4685,7050z
From 218eb2b332709aada4fafefdbb55985bee6c42f3 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Mon, 16 Jan 2023 21:33:29 +1100
Subject: [PATCH 52/79] Add sponsor to readme
add sponsor
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index cccbe401b..ef78e3cd0 100644
--- a/README.md
+++ b/README.md
@@ -330,6 +330,8 @@ And you can download
+
+
### Mentions
From 2e4127c63b0de314f155c19e154a30c6c1294cba Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 00:37:05 +0800
Subject: [PATCH 53/79] Catch specifc exception
---
.../Search/SearchManager.cs | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 93a81f947..b3c118fca 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -105,14 +105,16 @@ namespace Flow.Launcher.Plugin.Explorer.Search
await foreach (var search in searchResults.WithCancellation(token).ConfigureAwait(false))
results.Add(ResultManager.CreateResult(query, search));
}
+ catch (OperationCanceledException)
+ {
+ return results.ToList();
+ }
+ catch (EngineNotAvailableException)
+ {
+ throw;
+ }
catch (Exception e)
{
- if (e is OperationCanceledException)
- return results.ToList();
-
- if (e is EngineNotAvailableException)
- throw;
-
throw new SearchException(engineName, e.Message, e);
}
From 6efa9d1731fee3de894566eb558c0f92111cdaeb Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 00:40:54 +0800
Subject: [PATCH 54/79] Only expand environment var when path starts with %
---
Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index b3c118fca..45ba690d3 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -175,7 +175,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
return EnvironmentVariables.GetEnvironmentStringPathSuggestions(querySearch, query, Context);
// Query is a location path with a full environment variable, eg. %appdata%\somefolder\
- var isEnvironmentVariablePath = querySearch[1..].Contains("%\\");
+ var isEnvironmentVariablePath = querySearch[0] == '%' && querySearch[1..].Contains("%\\");
var locationPath = querySearch;
From 983f0aafc4267fa64b9469d72710532aa9b027fd Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 00:49:24 +0800
Subject: [PATCH 55/79] Use a static dictionary for environment vars
---
.../Search/EnvironmentVariables.cs | 31 +++++++++++++------
1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
index 595ac3610..fae5f59cd 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
@@ -8,12 +8,25 @@ namespace Flow.Launcher.Plugin.Explorer.Search
{
public static class EnvironmentVariables
{
+ private static Dictionary _envStringPaths = null;
+ private static Dictionary EnvStringPaths
+ {
+ get
+ {
+ if (_envStringPaths == null)
+ {
+ _envStringPaths = LoadEnvironmentStringPaths();
+ }
+ return _envStringPaths;
+ }
+ }
+
internal static bool IsEnvironmentVariableSearch(string search)
{
return search.StartsWith("%")
&& search != "%%"
- && !search.Contains("\\") &&
- LoadEnvironmentStringPaths().Count > 0;
+ && !search.Contains("\\")
+ && EnvStringPaths.Count > 0;
}
internal static Dictionary LoadEnvironmentStringPaths()
@@ -44,15 +57,14 @@ namespace Flow.Launcher.Plugin.Explorer.Search
internal static string TranslateEnvironmentVariablePath(string environmentVariablePath)
{
- var envStringPaths = LoadEnvironmentStringPaths();
var splitSearch = environmentVariablePath.Substring(1).Split("%");
var exactEnvStringPath = splitSearch[0];
// if there are more than 2 % characters in the query, don't bother
- if (splitSearch.Length == 2 && envStringPaths.ContainsKey(exactEnvStringPath))
+ if (splitSearch.Length == 2 && EnvStringPaths.ContainsKey(exactEnvStringPath))
{
var queryPartToReplace = $"%{exactEnvStringPath}%";
- var expandedPath = envStringPaths[exactEnvStringPath];
+ var expandedPath = EnvStringPaths[exactEnvStringPath];
// replace the %envstring% part of the query with its expanded equivalent
return environmentVariablePath.Replace(queryPartToReplace, expandedPath);
}
@@ -64,7 +76,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search
{
var results = new List();
- var environmentVariables = LoadEnvironmentStringPaths();
var search = querySearch;
if (querySearch.EndsWith("%") && search.Length > 1)
@@ -72,9 +83,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search
// query starts and ends with a %, find an exact match from env-string paths
search = querySearch.Substring(1, search.Length - 2);
- if (environmentVariables.ContainsKey(search))
+ if (EnvStringPaths.ContainsKey(search))
{
- var expandedPath = environmentVariables[search];
+ var expandedPath = EnvStringPaths[search];
results.Add(ResultManager.CreateFolderResult($"%{search}%", expandedPath, expandedPath, query));
@@ -91,7 +102,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
search = search.Substring(1);
}
- foreach (var p in environmentVariables)
+ foreach (var p in EnvStringPaths)
{
if (p.Key.StartsWith(search, StringComparison.InvariantCultureIgnoreCase))
{
From 009ee3dc5c7a35daa36872f77a2f999cb8001815 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 12:34:36 +0800
Subject: [PATCH 56/79] Simplify environment variable detection
---
.../Search/EnvironmentVariables.cs | 29 +++++++------------
.../Search/SearchManager.cs | 2 +-
2 files changed, 12 insertions(+), 19 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
index fae5f59cd..3d6a1ad8a 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
@@ -23,12 +23,17 @@ namespace Flow.Launcher.Plugin.Explorer.Search
internal static bool IsEnvironmentVariableSearch(string search)
{
- return search.StartsWith("%")
+ return search.StartsWith("%")
&& search != "%%"
- && !search.Contains("\\")
+ && !search.Contains('\\')
&& EnvStringPaths.Count > 0;
}
+ internal static bool BeginsWithEnvironmentVar(string search)
+ {
+ return search[0] == '%' && search[1..].Contains("%\\");
+ }
+
internal static Dictionary LoadEnvironmentStringPaths()
{
var envStringPaths = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
@@ -57,19 +62,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
internal static string TranslateEnvironmentVariablePath(string environmentVariablePath)
{
- var splitSearch = environmentVariablePath.Substring(1).Split("%");
- var exactEnvStringPath = splitSearch[0];
-
- // if there are more than 2 % characters in the query, don't bother
- if (splitSearch.Length == 2 && EnvStringPaths.ContainsKey(exactEnvStringPath))
- {
- var queryPartToReplace = $"%{exactEnvStringPath}%";
- var expandedPath = EnvStringPaths[exactEnvStringPath];
- // replace the %envstring% part of the query with its expanded equivalent
- return environmentVariablePath.Replace(queryPartToReplace, expandedPath);
- }
-
- return environmentVariablePath;
+ return Environment.ExpandEnvironmentVariables(environmentVariablePath);
}
internal static List GetEnvironmentStringPathSuggestions(string querySearch, Query query, PluginInitContext context)
@@ -86,9 +79,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search
if (EnvStringPaths.ContainsKey(search))
{
var expandedPath = EnvStringPaths[search];
-
+
results.Add(ResultManager.CreateFolderResult($"%{search}%", expandedPath, expandedPath, query));
-
+
return results;
}
}
@@ -101,7 +94,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
{
search = search.Substring(1);
}
-
+
foreach (var p in EnvStringPaths)
{
if (p.Key.StartsWith(search, StringComparison.InvariantCultureIgnoreCase))
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 45ba690d3..677b7f038 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -175,7 +175,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
return EnvironmentVariables.GetEnvironmentStringPathSuggestions(querySearch, query, Context);
// Query is a location path with a full environment variable, eg. %appdata%\somefolder\
- var isEnvironmentVariablePath = querySearch[0] == '%' && querySearch[1..].Contains("%\\");
+ var isEnvironmentVariablePath = EnvironmentVariables.BeginsWithEnvironmentVar(querySearch);
var locationPath = querySearch;
From 52e72992c2d417e2fd5b3e149a568aa0fef6aabe Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 14:47:42 +0800
Subject: [PATCH 57/79] Change context and settings to non static
---
Flow.Launcher.Test/Plugins/ExplorerTest.cs | 3 ++-
.../Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 8 ++++----
.../Search/WindowsIndex/WindowsIndexSearchManager.cs | 6 +++---
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/Flow.Launcher.Test/Plugins/ExplorerTest.cs b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
index 36f0294a9..4075947ff 100644
--- a/Flow.Launcher.Test/Plugins/ExplorerTest.cs
+++ b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
@@ -176,7 +176,7 @@ namespace Flow.Launcher.Test.Plugins
var searchManager = new SearchManager(new Settings(), new PluginInitContext());
// When
- var result = SearchManager.IsFileContentSearch(query.ActionKeyword);
+ var result = searchManager.IsFileContentSearch(query.ActionKeyword);
// Then
Assert.IsTrue(result,
@@ -193,6 +193,7 @@ namespace Flow.Launcher.Test.Plugins
[TestCase(@"c:\>*", true)]
[TestCase(@"c:\>", true)]
[TestCase(@"c:\SomeLocation\SomeOtherLocation\>", true)]
+ [TestCase(@"c:\SomeLocation\SomeOtherLocation", true)]
public void WhenGivenQuerySearchString_ThenShouldIndicateIfIsLocationPathString(string querySearchString, bool expectedResult)
{
// When, Given
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 677b7f038..ce1283e06 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -13,9 +13,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search
{
public class SearchManager
{
- internal static PluginInitContext Context;
+ internal PluginInitContext Context;
- internal static Settings Settings;
+ internal Settings Settings;
public SearchManager(Settings settings, PluginInitContext context)
{
@@ -144,7 +144,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
};
}
- private static List EverythingContentSearchResult(Query query)
+ private List EverythingContentSearchResult(Query query)
{
return new List()
{
@@ -236,7 +236,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
return results.ToList();
}
- public static bool IsFileContentSearch(string actionKeyword) => actionKeyword == Settings.FileContentSearchActionKeyword;
+ public bool IsFileContentSearch(string actionKeyword) => actionKeyword == Settings.FileContentSearchActionKeyword;
private bool UseWindowsIndexForDirectorySearch(string locationPath)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
index abb50849d..f1060a4ac 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
@@ -97,10 +97,10 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
private IAsyncEnumerable HandledEngineNotAvailableExceptionAsync()
{
- if (!SearchManager.Settings.WarnWindowsSearchServiceOff)
+ if (!Settings.WarnWindowsSearchServiceOff)
return AsyncEnumerable.Empty();
- var api = SearchManager.Context.API;
+ var api = Main.Context.API;
throw new EngineNotAvailableException(
"Windows Index",
@@ -108,7 +108,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
api.GetTranslation("plugin_explorer_windowsSearchServiceNotRunning"),
c =>
{
- SearchManager.Settings.WarnWindowsSearchServiceOff = false;
+ Settings.WarnWindowsSearchServiceOff = false;
// Clears the warning message so user is not mistaken that it has not worked
api.ChangeQuery(string.Empty);
From 51f5d8a410e1708280e1c7e48c23951b4c8db37d Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 14:48:35 +0800
Subject: [PATCH 58/79] Add new constructor for EngineNotAvailableException
---
.../Exceptions/EngineNotAvailableException.cs | 21 +++++++++++++++---
.../Everything/EverythingSearchManager.cs | 22 +++++++------------
.../WindowsIndex/WindowsIndexSearchManager.cs | 6 ++---
3 files changed, 28 insertions(+), 21 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Exceptions/EngineNotAvailableException.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Exceptions/EngineNotAvailableException.cs
index 1a48892f5..a6315fb4b 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Exceptions/EngineNotAvailableException.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Exceptions/EngineNotAvailableException.cs
@@ -3,8 +3,6 @@
using System;
using System.Threading.Tasks;
using System.Windows;
-using Flow.Launcher.Plugin.Explorer.Search.IProvider;
-using JetBrains.Annotations;
namespace Flow.Launcher.Plugin.Explorer.Exceptions;
@@ -20,7 +18,7 @@ public class EngineNotAvailableException : Exception
string engineName,
string resolution,
string message,
- Func> action = null) : base(message)
+ Func>? action = null) : base(message)
{
EngineName = engineName;
Resolution = resolution;
@@ -40,6 +38,23 @@ public class EngineNotAvailableException : Exception
EngineName = engineName;
Resolution = resolution;
}
+
+ public EngineNotAvailableException(
+ string engineName,
+ string resolution,
+ string message,
+ string errorIconPath,
+ Func>? action = null) : base(message)
+ {
+ EngineName = engineName;
+ Resolution = resolution;
+ ErrorIcon = errorIconPath;
+ Action = action ?? (_ =>
+ {
+ Clipboard.SetDataObject(this.ToString());
+ return ValueTask.FromResult(true);
+ });
+ }
public override string ToString()
{
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs
index ffd22d9f5..4bb8a0cdd 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs
@@ -27,20 +27,16 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything
Enum.GetName(Settings.IndexSearchEngineOption.Everything)!,
Main.Context.API.GetTranslation("flowlauncher_plugin_everything_click_to_launch_or_install"),
Main.Context.API.GetTranslation("flowlauncher_plugin_everything_is_not_running"),
- ClickToInstallEverythingAsync)
- {
- ErrorIcon = Constants.EverythingErrorImagePath
- };
+ Constants.EverythingErrorImagePath,
+ ClickToInstallEverythingAsync);
}
catch (DllNotFoundException)
{
throw new EngineNotAvailableException(
Enum.GetName(Settings.IndexSearchEngineOption.Everything)!,
"Please check whether your system is x86 or x64",
- Main.Context.API.GetTranslation("flowlauncher_plugin_everything_sdk_issue"))
- {
- ErrorIcon = Constants.GeneralSearchErrorImagePath
- };
+ Constants.GeneralSearchErrorImagePath,
+ Main.Context.API.GetTranslation("flowlauncher_plugin_everything_sdk_issue"));
}
}
private async ValueTask ClickToInstallEverythingAsync(ActionContext _)
@@ -72,16 +68,14 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything
if (!Settings.EnableEverythingContentSearch)
{
throw new EngineNotAvailableException(Enum.GetName(Settings.IndexSearchEngineOption.Everything)!,
- "Click to Enable Everything Content Search (only applicable to Everything 1.5+ with indexed content)",
- "Everything Content Search is not enabled.",
+ Main.Context.API.GetTranslation("flowlauncher_plugin_everything_enable_content_search"),
+ Main.Context.API.GetTranslation("flowlauncher_plugin_everything_enable_content_search_tips"),
+ Constants.EverythingErrorImagePath,
_ =>
{
Settings.EnableEverythingContentSearch = true;
return ValueTask.FromResult(true);
- })
- {
- ErrorIcon = Constants.EverythingErrorImagePath
- };
+ });
}
if (token.IsCancellationRequested)
yield break;
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
index f1060a4ac..c3a7d9e91 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
@@ -106,6 +106,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
"Windows Index",
api.GetTranslation("plugin_explorer_windowsSearchServiceFix"),
api.GetTranslation("plugin_explorer_windowsSearchServiceNotRunning"),
+ Constants.WindowsIndexErrorImagePath,
c =>
{
Settings.WarnWindowsSearchServiceOff = false;
@@ -114,10 +115,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
api.ChangeQuery(string.Empty);
return ValueTask.FromResult(false);
- })
- {
- ErrorIcon = Constants.WindowsIndexErrorImagePath
- };
+ });
}
}
}
From 383298a46bca314c26f1f6c1738c1935c35dcf19 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 16:04:41 +0800
Subject: [PATCH 59/79] Fix null subtitle when creating disk result
---
Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs
index 62ad71608..ed4f39735 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs
@@ -71,7 +71,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
{
Title = title,
IcoPath = path,
- SubTitle = Path.GetDirectoryName(path),
+ SubTitle = subtitle,
AutoCompleteText = GetAutoCompleteText(title, query, path, ResultType.Folder),
TitleHighlightData = StringMatcher.FuzzySearch(query.Search, title).MatchData,
CopyText = path,
From a6b7c5898b1a472b3d377f40e2b089b8d5c472b1 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 16:05:39 +0800
Subject: [PATCH 60/79] Fix subpath check
---
.../Search/SearchManager.cs | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index ce1283e06..4a25fe0ad 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -8,6 +8,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Flow.Launcher.Plugin.Explorer.Exceptions;
+using System.IO;
namespace Flow.Launcher.Plugin.Explorer.Search
{
@@ -119,7 +120,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
}
results.RemoveWhere(r => Settings.IndexSearchExcludedSubdirectoryPaths.Any(
- excludedPath => r.SubTitle.StartsWith(excludedPath.Path, StringComparison.OrdinalIgnoreCase)));
+ excludedPath => IsSubPathOf(r.SubTitle, excludedPath.Path)));
return results.ToList();
}
@@ -254,5 +255,16 @@ namespace Flow.Launcher.Plugin.Explorer.Search
&& search != "%%"
&& !search.Contains('\\');
}
+
+ // https://stackoverflow.com/a/66877016
+ internal static bool IsSubPathOf(string subPath, string basePath)
+ {
+ var rel = Path.GetRelativePath(basePath, subPath);
+ return rel != "."
+ && rel != ".."
+ && !rel.StartsWith("../")
+ && !rel.StartsWith(@"..\")
+ && !Path.IsPathRooted(rel);
+ }
}
}
From 2c36692052f1f43782ee6f7f3fdf8416b7f7f6c7 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 16:06:01 +0800
Subject: [PATCH 61/79] Use case-insensitve comparator for path
---
.../Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 4a25fe0ad..da6509124 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -31,12 +31,13 @@ namespace Flow.Launcher.Plugin.Explorer.Search
public bool Equals(Result x, Result y)
{
- return x.Title == y.Title && x.SubTitle == y.SubTitle;
+ return x.Title.Equals(y.Title, StringComparison.OrdinalIgnoreCase)
+ && string.Equals(x.SubTitle, y.SubTitle, StringComparison.OrdinalIgnoreCase);
}
public int GetHashCode(Result obj)
{
- return HashCode.Combine(obj.Title.GetHashCode(), obj.SubTitle?.GetHashCode() ?? 0);
+ return HashCode.Combine(obj.Title.ToLowerInvariant(), obj.SubTitle?.ToLowerInvariant() ?? "");
}
}
@@ -118,7 +119,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
{
throw new SearchException(engineName, e.Message, e);
}
-
+
results.RemoveWhere(r => Settings.IndexSearchExcludedSubdirectoryPaths.Any(
excludedPath => IsSubPathOf(r.SubTitle, excludedPath.Path)));
From 32268890b964e4e125ba81973541aa9588f05335 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 20:23:33 +0800
Subject: [PATCH 62/79] Remove TranslateEnvironmentVariablePath
---
.../Search/EnvironmentVariables.cs | 5 -----
.../Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 4 ++--
2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
index 3d6a1ad8a..c17277112 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
@@ -60,11 +60,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search
return envStringPaths;
}
- internal static string TranslateEnvironmentVariablePath(string environmentVariablePath)
- {
- return Environment.ExpandEnvironmentVariables(environmentVariablePath);
- }
-
internal static List GetEnvironmentStringPathSuggestions(string querySearch, Query query, PluginInitContext context)
{
var results = new List();
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index da6509124..25604cf2f 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -178,11 +178,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search
// Query is a location path with a full environment variable, eg. %appdata%\somefolder\
var isEnvironmentVariablePath = EnvironmentVariables.BeginsWithEnvironmentVar(querySearch);
-
+
var locationPath = querySearch;
if (isEnvironmentVariablePath)
- locationPath = EnvironmentVariables.TranslateEnvironmentVariablePath(locationPath);
+ locationPath = Environment.ExpandEnvironmentVariables(locationPath);
// Check that actual location exists, otherwise directory search will throw directory not found exception
if (!FilesFolders.ReturnPreviousDirectoryIfIncompleteString(locationPath).LocationExists())
From ac92b93f669feb512a0ef0cb2ec1364f9b2b3377 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 20:29:25 +0800
Subject: [PATCH 63/79] Move IsSubPathOf to SharedCommands
---
.../SharedCommands/FilesFolders.cs | 17 +++++++++++++++++
.../Search/SearchManager.cs | 13 +------------
.../Programs/Win32.cs | 15 ++-------------
3 files changed, 20 insertions(+), 25 deletions(-)
diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
index 5cb3a171a..97d8c25d3 100644
--- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
+++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
@@ -241,5 +241,22 @@ namespace Flow.Launcher.Plugin.SharedCommands
return path;
}
+
+ ///
+ /// Returns if is a sub path of .
+ /// From https://stackoverflow.com/a/66877016
+ ///
+ ///
+ ///
+ ///
+ public static bool IsSubPathOf(string subPath, string basePath)
+ {
+ var rel = Path.GetRelativePath(basePath, subPath);
+ return rel != "."
+ && rel != ".."
+ && !rel.StartsWith("../")
+ && !rel.StartsWith(@"..\")
+ && !Path.IsPathRooted(rel);
+ }
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 25604cf2f..324832990 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -121,7 +121,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
}
results.RemoveWhere(r => Settings.IndexSearchExcludedSubdirectoryPaths.Any(
- excludedPath => IsSubPathOf(r.SubTitle, excludedPath.Path)));
+ excludedPath => FilesFolders.IsSubPathOf(r.SubTitle, excludedPath.Path)));
return results.ToList();
}
@@ -256,16 +256,5 @@ namespace Flow.Launcher.Plugin.Explorer.Search
&& search != "%%"
&& !search.Contains('\\');
}
-
- // https://stackoverflow.com/a/66877016
- internal static bool IsSubPathOf(string subPath, string basePath)
- {
- var rel = Path.GetRelativePath(basePath, subPath);
- return rel != "."
- && rel != ".."
- && !rel.StartsWith("../")
- && !rel.StartsWith(@"..\")
- && !Path.IsPathRooted(rel);
- }
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
index f678b6bc8..28eb9832f 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
@@ -471,7 +471,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
var paths = pathEnv.Split(";", StringSplitOptions.RemoveEmptyEntries).DistinctBy(p => p.ToLowerInvariant());
- var toFilter = paths.Where(x => commonParents.All(parent => !IsSubPathOf(x, parent)))
+ var toFilter = paths.Where(x => commonParents.All(parent => !FilesFolders.IsSubPathOf(x, parent)))
.AsParallel()
.SelectMany(p => EnumerateProgramsInDir(p, suffixes, recursive: false));
@@ -763,17 +763,6 @@ namespace Flow.Launcher.Plugin.Program.Programs
}
}
- // https://stackoverflow.com/a/66877016
- private static bool IsSubPathOf(string subPath, string basePath)
- {
- var rel = Path.GetRelativePath(basePath, subPath);
- return rel != "."
- && rel != ".."
- && !rel.StartsWith("../")
- && !rel.StartsWith(@"..\")
- && !Path.IsPathRooted(rel);
- }
-
private static List GetCommonParents(IEnumerable programSources)
{
// To avoid unnecessary io
@@ -785,7 +774,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
HashSet parents = group.ToHashSet();
foreach (var source in group)
{
- if (parents.Any(p => IsSubPathOf(source.Location, p.Location) &&
+ if (parents.Any(p => FilesFolders.IsSubPathOf(source.Location, p.Location) &&
source != p))
{
parents.Remove(source);
From beb144956c2d1c6163a5dd7f96486f5edd80c2a5 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 21:33:09 +0800
Subject: [PATCH 64/79] Rename method and add option to allow equality
---
.../SharedCommands/FilesFolders.cs | 14 +++++++-------
.../Search/SearchManager.cs | 2 +-
.../Flow.Launcher.Plugin.Program/Programs/Win32.cs | 7 +++----
3 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
index 97d8c25d3..c59f05598 100644
--- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
+++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
@@ -1,7 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
-using System.Windows;
namespace Flow.Launcher.Plugin.SharedCommands
{
@@ -243,16 +242,17 @@ namespace Flow.Launcher.Plugin.SharedCommands
}
///
- /// Returns if is a sub path of .
+ /// Returns if contains .
/// From https://stackoverflow.com/a/66877016
///
- ///
- ///
+ /// Parent path
+ /// Sub path
+ /// If , when and are equal, returns
///
- public static bool IsSubPathOf(string subPath, string basePath)
+ public static bool PathContains(string parentPath, string subPath, bool allowEqual = false)
{
- var rel = Path.GetRelativePath(basePath, subPath);
- return rel != "."
+ var rel = Path.GetRelativePath(parentPath, subPath);
+ return (rel != "." || allowEqual)
&& rel != ".."
&& !rel.StartsWith("../")
&& !rel.StartsWith(@"..\")
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 324832990..3a1dc3726 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -121,7 +121,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
}
results.RemoveWhere(r => Settings.IndexSearchExcludedSubdirectoryPaths.Any(
- excludedPath => FilesFolders.IsSubPathOf(r.SubTitle, excludedPath.Path)));
+ excludedPath => FilesFolders.PathContains(excludedPath.Path, r.SubTitle)));
return results.ToList();
}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
index 28eb9832f..e0079967b 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
@@ -470,8 +470,8 @@ namespace Flow.Launcher.Plugin.Program.Programs
}
var paths = pathEnv.Split(";", StringSplitOptions.RemoveEmptyEntries).DistinctBy(p => p.ToLowerInvariant());
-
- var toFilter = paths.Where(x => commonParents.All(parent => !FilesFolders.IsSubPathOf(x, parent)))
+
+ var toFilter = paths.Where(x => commonParents.All(parent => !FilesFolders.PathContains(parent, x)))
.AsParallel()
.SelectMany(p => EnumerateProgramsInDir(p, suffixes, recursive: false));
@@ -774,8 +774,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
HashSet parents = group.ToHashSet();
foreach (var source in group)
{
- if (parents.Any(p => FilesFolders.IsSubPathOf(source.Location, p.Location) &&
- source != p))
+ if (parents.Any(p => FilesFolders.PathContains(p.Location, source.Location)))
{
parents.Remove(source);
}
From b42fc54b806285067dd2c22cf600fd22c174c3b7 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 21:33:21 +0800
Subject: [PATCH 65/79] Add test for PathContains()
---
Flow.Launcher.Test/FilesFoldersTest.cs | 53 ++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
create mode 100644 Flow.Launcher.Test/FilesFoldersTest.cs
diff --git a/Flow.Launcher.Test/FilesFoldersTest.cs b/Flow.Launcher.Test/FilesFoldersTest.cs
new file mode 100644
index 000000000..656395591
--- /dev/null
+++ b/Flow.Launcher.Test/FilesFoldersTest.cs
@@ -0,0 +1,53 @@
+using Flow.Launcher.Plugin.SharedCommands;
+using NUnit.Framework;
+
+namespace Flow.Launcher.Test
+{
+ [TestFixture]
+
+ public class FilesFoldersTest
+ {
+ // Testcases from https://stackoverflow.com/a/31941905/20703207
+ // Disk
+ [TestCase(@"c:", @"c:\foo", true)]
+ [TestCase(@"c:\", @"c:\foo", true)]
+ // Slash
+ [TestCase(@"c:\foo\bar\", @"c:\foo\", false)]
+ [TestCase(@"c:\foo\bar", @"c:\foo\", false)]
+ [TestCase(@"c:\foo", @"c:\foo\bar", true)]
+ [TestCase(@"c:\foo\", @"c:\foo\bar", true)]
+ // File
+ [TestCase(@"c:\foo", @"c:\foo\a.txt", true)]
+ [TestCase(@"c:\foo", @"c:/foo/a.txt", true)]
+ [TestCase(@"c:\FOO\a.txt", @"c:\foo", false)]
+ [TestCase(@"c:\foo\a.txt", @"c:\foo\", false)]
+ [TestCase(@"c:\foobar\a.txt", @"c:\foo", false)]
+ [TestCase(@"c:\foobar\a.txt", @"c:\foo\", false)]
+ [TestCase(@"c:\foo\", @"c:\foo.txt", false)]
+ // Prefix
+ [TestCase(@"c:\foo", @"c:\foobar", false)]
+ [TestCase(@"C:\Program", @"C:\Program Files\", false)]
+ [TestCase(@"c:\foobar", @"c:\foo\a.txt", false)]
+ [TestCase(@"c:\foobar\", @"c:\foo\a.txt", false)]
+ // Edge case
+ [TestCase(@"c:\foo", @"c:\foo\..\bar\baz", false)]
+ [TestCase(@"c:\bar", @"c:\foo\..\bar\baz", true)]
+ [TestCase(@"c:\barr", @"c:\foo\..\bar\baz", false)]
+ // Equality
+ [TestCase(@"c:\foo", @"c:\foo", false)]
+ [TestCase(@"c:\foo\", @"c:\foo", false)]
+ [TestCase(@"c:\foo", @"c:\foo\", false)]
+ public void TestPathContains(string parentPath, string path, bool expectedResult)
+ {
+ Assert.AreEqual(expectedResult, FilesFolders.PathContains(parentPath, path));
+ }
+
+ [TestCase(@"c:\foo", @"c:\foo", true)]
+ [TestCase(@"c:\foo\", @"c:\foo", true)]
+ [TestCase(@"c:\foo\", @"c:\foo", true)]
+ public void TestPathContainsWhenEqual(string parentPath, string path, bool expectedResult)
+ {
+ Assert.AreEqual(expectedResult, FilesFolders.PathContains(parentPath, path, true));
+ }
+ }
+}
From 4bea50d4cf9c738f03440e03d21f9801227b51ec Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 23:16:12 +0800
Subject: [PATCH 66/79] Add unit test for PathEqualityComparator
---
Flow.Launcher.Test/FilesFoldersTest.cs | 2 +-
Flow.Launcher.Test/Plugins/ExplorerTest.cs | 41 +++++++++++++++++++
.../Search/SearchManager.cs | 14 ++++---
3 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/Flow.Launcher.Test/FilesFoldersTest.cs b/Flow.Launcher.Test/FilesFoldersTest.cs
index 656395591..a65cc600d 100644
--- a/Flow.Launcher.Test/FilesFoldersTest.cs
+++ b/Flow.Launcher.Test/FilesFoldersTest.cs
@@ -44,7 +44,7 @@ namespace Flow.Launcher.Test
[TestCase(@"c:\foo", @"c:\foo", true)]
[TestCase(@"c:\foo\", @"c:\foo", true)]
- [TestCase(@"c:\foo\", @"c:\foo", true)]
+ [TestCase(@"c:\foo", @"c:\foo\", true)]
public void TestPathContainsWhenEqual(string parentPath, string path, bool expectedResult)
{
Assert.AreEqual(expectedResult, FilesFolders.PathContains(parentPath, path, true));
diff --git a/Flow.Launcher.Test/Plugins/ExplorerTest.cs b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
index 4075947ff..322441247 100644
--- a/Flow.Launcher.Test/Plugins/ExplorerTest.cs
+++ b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
@@ -7,9 +7,11 @@ using Flow.Launcher.Plugin.SharedCommands;
using NUnit.Framework;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
+using static Flow.Launcher.Plugin.Explorer.Search.SearchManager;
namespace Flow.Launcher.Test.Plugins
{
@@ -394,5 +396,44 @@ namespace Flow.Launcher.Test.Plugins
// Then
Assert.AreEqual(result, expectedResult);
}
+
+ [TestCase(@"c:\foo", @"c:\foo", true)]
+ [TestCase(@"C:\Foo\", @"c:\foo\", true)]
+ [TestCase(@"c:\foo", @"c:\foo\", false)]
+ public void PathEqualityComparatorEquality(string path1, string path2, bool expectedResult)
+ {
+ var comparator = PathEqualityComparator.Instance;
+ var result1 = new Result
+ {
+ Title = Path.GetFileName(path1),
+ SubTitle = path1
+ };
+ var result2 = new Result
+ {
+ Title = Path.GetFileName(path2),
+ SubTitle = path2
+ };
+ Assert.AreEqual(expectedResult, comparator.Equals(result1, result2));
+ }
+
+ [TestCase(@"c:\foo\", @"c:\foo\")]
+ [TestCase(@"C:\Foo\", @"c:\foo\")]
+ public void PathEqualityComparatorHashCode(string path1, string path2)
+ {
+ var comparator = PathEqualityComparator.Instance;
+ var result1 = new Result
+ {
+ Title = Path.GetFileName(path1),
+ SubTitle = path1
+ };
+ var result2 = new Result
+ {
+ Title = Path.GetFileName(path2),
+ SubTitle = path2
+ };
+ var hash1 = comparator.GetHashCode(result1);
+ var hash2 = comparator.GetHashCode(result2);
+ Assert.IsTrue(hash1 == hash2);
+ }
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 3a1dc3726..0a40590ba 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -8,7 +8,6 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Flow.Launcher.Plugin.Explorer.Exceptions;
-using System.IO;
namespace Flow.Launcher.Plugin.Explorer.Search
{
@@ -24,14 +23,17 @@ namespace Flow.Launcher.Plugin.Explorer.Search
Settings = settings;
}
- private class PathEqualityComparator : IEqualityComparer
+ ///
+ /// Note: Assuming all diretories end with "\".
+ ///
+ public class PathEqualityComparator : IEqualityComparer
{
private static PathEqualityComparator instance;
public static PathEqualityComparator Instance => instance ??= new PathEqualityComparator();
public bool Equals(Result x, Result y)
{
- return x.Title.Equals(y.Title, StringComparison.OrdinalIgnoreCase)
+ return x.Title.Equals(y.Title, StringComparison.OrdinalIgnoreCase)
&& string.Equals(x.SubTitle, y.SubTitle, StringComparison.OrdinalIgnoreCase);
}
@@ -178,7 +180,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
// Query is a location path with a full environment variable, eg. %appdata%\somefolder\
var isEnvironmentVariablePath = EnvironmentVariables.BeginsWithEnvironmentVar(querySearch);
-
+
var locationPath = querySearch;
if (isEnvironmentVariablePath)
@@ -249,10 +251,10 @@ namespace Flow.Launcher.Plugin.Explorer.Search
x => FilesFolders.ReturnPreviousDirectoryIfIncompleteString(pathToDirectory).StartsWith(x.Path, StringComparison.OrdinalIgnoreCase))
&& WindowsIndex.WindowsIndex.PathIsIndexed(pathToDirectory);
}
-
+
internal static bool IsEnvironmentVariableSearch(string search)
{
- return search.StartsWith("%")
+ return search.StartsWith("%")
&& search != "%%"
&& !search.Contains('\\');
}
From 03f062ca34c49e6cb6223f867718436116969ddd Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Thu, 19 Jan 2023 23:26:10 +0800
Subject: [PATCH 67/79] Fix build error
---
Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
index c59f05598..2ccc35884 100644
--- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
+++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
@@ -1,6 +1,9 @@
using System;
using System.Diagnostics;
using System.IO;
+#if !DEBUG
+using System.Windows;
+#endif
namespace Flow.Launcher.Plugin.SharedCommands
{
From fefb1378704291ae6e70ee8691640718333ac2f0 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 20 Jan 2023 07:45:39 +1100
Subject: [PATCH 68/79] fix test format
---
Flow.Launcher.Test/Plugins/ExplorerTest.cs | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher.Test/Plugins/ExplorerTest.cs b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
index 322441247..70c13f296 100644
--- a/Flow.Launcher.Test/Plugins/ExplorerTest.cs
+++ b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
@@ -400,8 +400,9 @@ namespace Flow.Launcher.Test.Plugins
[TestCase(@"c:\foo", @"c:\foo", true)]
[TestCase(@"C:\Foo\", @"c:\foo\", true)]
[TestCase(@"c:\foo", @"c:\foo\", false)]
- public void PathEqualityComparatorEquality(string path1, string path2, bool expectedResult)
+ public void GivenTwoPaths_WhenCompared_ThenShouldBeExpectedSameOrDifferent(string path1, string path2, bool expectedResult)
{
+ // Given
var comparator = PathEqualityComparator.Instance;
var result1 = new Result
{
@@ -413,13 +414,16 @@ namespace Flow.Launcher.Test.Plugins
Title = Path.GetFileName(path2),
SubTitle = path2
};
+
+ // When, Then
Assert.AreEqual(expectedResult, comparator.Equals(result1, result2));
}
[TestCase(@"c:\foo\", @"c:\foo\")]
[TestCase(@"C:\Foo\", @"c:\foo\")]
- public void PathEqualityComparatorHashCode(string path1, string path2)
+ public void GivenTwoPaths_WhenComparedHasCode_ThenShouldBeSame(string path1, string path2)
{
+ // Given
var comparator = PathEqualityComparator.Instance;
var result1 = new Result
{
@@ -431,8 +435,11 @@ namespace Flow.Launcher.Test.Plugins
Title = Path.GetFileName(path2),
SubTitle = path2
};
+
var hash1 = comparator.GetHashCode(result1);
var hash2 = comparator.GetHashCode(result2);
+
+ // When, Then
Assert.IsTrue(hash1 == hash2);
}
}
From b77bfea8875be532cafacfcefce6a14c34023ea6 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 20 Jan 2023 07:55:16 +1100
Subject: [PATCH 69/79] update test name
---
Flow.Launcher.Test/FilesFoldersTest.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher.Test/FilesFoldersTest.cs b/Flow.Launcher.Test/FilesFoldersTest.cs
index a65cc600d..d16826053 100644
--- a/Flow.Launcher.Test/FilesFoldersTest.cs
+++ b/Flow.Launcher.Test/FilesFoldersTest.cs
@@ -1,4 +1,4 @@
-using Flow.Launcher.Plugin.SharedCommands;
+using Flow.Launcher.Plugin.SharedCommands;
using NUnit.Framework;
namespace Flow.Launcher.Test
@@ -37,7 +37,7 @@ namespace Flow.Launcher.Test
[TestCase(@"c:\foo", @"c:\foo", false)]
[TestCase(@"c:\foo\", @"c:\foo", false)]
[TestCase(@"c:\foo", @"c:\foo\", false)]
- public void TestPathContains(string parentPath, string path, bool expectedResult)
+ public void GivenTwoPaths_WhenCheckPathContains_ThenShouldBeExpectedResult(string parentPath, string path, bool expectedResult)
{
Assert.AreEqual(expectedResult, FilesFolders.PathContains(parentPath, path));
}
@@ -45,7 +45,7 @@ namespace Flow.Launcher.Test
[TestCase(@"c:\foo", @"c:\foo", true)]
[TestCase(@"c:\foo\", @"c:\foo", true)]
[TestCase(@"c:\foo", @"c:\foo\", true)]
- public void TestPathContainsWhenEqual(string parentPath, string path, bool expectedResult)
+ public void GivenTwoPathsAreTheSame_WhenCheckPathContains_ThenShouldBeTrue(string parentPath, string path, bool expectedResult)
{
Assert.AreEqual(expectedResult, FilesFolders.PathContains(parentPath, path, true));
}
From 768ed4f80a2b7f83530ff7698cdc0fb30a87fe59 Mon Sep 17 00:00:00 2001
From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Fri, 20 Jan 2023 12:13:02 +0800
Subject: [PATCH 70/79] Update wording
Co-authored-by: Jeremy Wu
---
Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 0a40590ba..916399e5c 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -24,7 +24,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
}
///
- /// Note: Assuming all diretories end with "\".
+ /// Note: A path that ends with "\" and one that doesn't will not be regarded as equal.
///
public class PathEqualityComparator : IEqualityComparer
{
From 504fb4ae0588735635955ac5a580e01baafc6175 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Fri, 20 Jan 2023 14:02:04 +0800
Subject: [PATCH 71/79] Display environment vars in upper case
---
.../Search/EnvironmentVariables.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
index c17277112..130de2ab1 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
@@ -52,8 +52,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search
path = Path.IsPathFullyQualified(path) ? path : Path.GetFullPath(path);
// Variables are returned with a mixture of all upper/lower case.
- // Call ToLower() to make the results look consistent
- envStringPaths.Add(special.Key.ToString().ToLower(), path);
+ // Call ToUpper() to make the results look consistent
+ envStringPaths.Add(special.Key.ToString().ToUpper(), path);
}
}
From 4d267fe71ee0f3aeb88f8781cb9aa4f5739cb49d Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Fri, 20 Jan 2023 14:27:12 +0800
Subject: [PATCH 72/79] Fix incorrect %homepath% parsing
Parse environment variables before checking path existence
---
.../SharedCommands/FilesFolders.cs | 10 ++++++++++
.../Search/EnvironmentVariables.cs | 20 ++++++++++---------
2 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
index 2ccc35884..42a0e0c73 100644
--- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
+++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
@@ -261,5 +261,15 @@ namespace Flow.Launcher.Plugin.SharedCommands
&& !rel.StartsWith(@"..\")
&& !Path.IsPathRooted(rel);
}
+
+ ///
+ /// Returns path ended with "\"
+ ///
+ ///
+ ///
+ public static string EnsureTrailingSlash(this string path)
+ {
+ return path.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
+ }
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
index 130de2ab1..a649de58e 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
@@ -2,7 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
-using System.Text;
+using Flow.Launcher.Plugin.SharedCommands;
namespace Flow.Launcher.Plugin.Explorer.Search
{
@@ -37,20 +37,22 @@ namespace Flow.Launcher.Plugin.Explorer.Search
internal static Dictionary LoadEnvironmentStringPaths()
{
var envStringPaths = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
+ var homedrive = Environment.GetEnvironmentVariable("HOMEDRIVE")?.EnsureTrailingSlash() ?? "C:\\";
foreach (DictionaryEntry special in Environment.GetEnvironmentVariables())
{
var path = special.Value.ToString();
+ // we add a trailing slash to the path to make sure drive paths become valid absolute paths.
+ // for example, if %systemdrive% is C: we turn it to C:\
+ path = path.EnsureTrailingSlash();
+
+ // if we don't have an absolute path, we use Path.GetFullPath to get one.
+ // for example, if %homepath% is \Users\John we turn it to C:\Users\John
+ // Add basepath for GetFullPath() to parse %HOMEPATH% correctly
+ path = Path.IsPathFullyQualified(path) ? path : Path.GetFullPath(path, homedrive);
+
if (Directory.Exists(path))
{
- // we add a trailing slash to the path to make sure drive paths become valid absolute paths.
- // for example, if %systemdrive% is C: we turn it to C:\
- path = path.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
-
- // if we don't have an absolute path, we use Path.GetFullPath to get one.
- // for example, if %homepath% is \Users\John we turn it to C:\Users\John
- path = Path.IsPathFullyQualified(path) ? path : Path.GetFullPath(path);
-
// Variables are returned with a mixture of all upper/lower case.
// Call ToUpper() to make the results look consistent
envStringPaths.Add(special.Key.ToString().ToUpper(), path);
From 966d3e752efc3f7e52a83bfb3d8e46b62478c6fc Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Fri, 20 Jan 2023 15:03:40 +0800
Subject: [PATCH 73/79] Fix environment variable expansion logic
---
Flow.Launcher.Test/Plugins/ExplorerTest.cs | 17 +++++++++++++++++
.../Search/EnvironmentVariables.cs | 10 ++++++++--
.../Search/SearchManager.cs | 14 ++++----------
3 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/Flow.Launcher.Test/Plugins/ExplorerTest.cs b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
index 70c13f296..e9d37433f 100644
--- a/Flow.Launcher.Test/Plugins/ExplorerTest.cs
+++ b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
@@ -442,5 +442,22 @@ namespace Flow.Launcher.Test.Plugins
// When, Then
Assert.IsTrue(hash1 == hash2);
}
+
+ [TestCase(@"%appdata%", true)]
+ [TestCase(@"%appdata%\123", true)]
+ [TestCase(@"c:\foo %appdata%\", false)]
+ [TestCase(@"c:\users\%USERNAME%\downloads", true)]
+ [TestCase(@"c:\downloads", false)]
+ [TestCase(@"%", false)]
+ [TestCase(@"%%", false)]
+ [TestCase(@"%bla%blabla%", false)]
+ public void GivenPath_WhenHavingEnvironmentVariableOrNot_ThenShouldBeExpected(string path, bool expectedResult)
+ {
+ // When
+ var result = EnvironmentVariables.HasEnvironmentVar(path);
+
+ // Then
+ Assert.AreEqual(result, expectedResult);
+ }
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
index a649de58e..5b0a5a8bd 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
@@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using Flow.Launcher.Plugin.SharedCommands;
namespace Flow.Launcher.Plugin.Explorer.Search
@@ -29,9 +30,14 @@ namespace Flow.Launcher.Plugin.Explorer.Search
&& EnvStringPaths.Count > 0;
}
- internal static bool BeginsWithEnvironmentVar(string search)
+ public static bool HasEnvironmentVar(string search)
{
- return search[0] == '%' && search[1..].Contains("%\\");
+ // "c:\foo %appdata%\" returns false
+ var splited = search.Split(Path.DirectorySeparatorChar);
+ return splited.Any(dir => dir.StartsWith('%') &&
+ dir.EndsWith('%') &&
+ dir.Length > 2 &&
+ dir.Split('%').Length == 3);
}
internal static Dictionary LoadEnvironmentStringPaths()
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 916399e5c..83057ff04 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -173,18 +173,12 @@ namespace Flow.Launcher.Plugin.Explorer.Search
var results = new HashSet(PathEqualityComparator.Instance);
- var isEnvironmentVariable = EnvironmentVariables.IsEnvironmentVariableSearch(querySearch);
-
- if (isEnvironmentVariable)
+ if (EnvironmentVariables.IsEnvironmentVariableSearch(querySearch))
return EnvironmentVariables.GetEnvironmentStringPathSuggestions(querySearch, query, Context);
- // Query is a location path with a full environment variable, eg. %appdata%\somefolder\
- var isEnvironmentVariablePath = EnvironmentVariables.BeginsWithEnvironmentVar(querySearch);
-
- var locationPath = querySearch;
-
- if (isEnvironmentVariablePath)
- locationPath = Environment.ExpandEnvironmentVariables(locationPath);
+ // Query is a location path with a full environment variable, eg. %appdata%\somefolder\, c:\users\%USERNAME%\downloads
+ var needToExpand = EnvironmentVariables.HasEnvironmentVar(querySearch);
+ var locationPath = needToExpand ? Environment.ExpandEnvironmentVariables(querySearch) : querySearch;
// Check that actual location exists, otherwise directory search will throw directory not found exception
if (!FilesFolders.ReturnPreviousDirectoryIfIncompleteString(locationPath).LocationExists())
From 71a2f996dbff2c92b219aa5641af01ef50870622 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Fri, 20 Jan 2023 15:27:19 +0800
Subject: [PATCH 74/79] Set environment var dict in
LoadEnvironmentStringPaths()
---
.../Search/EnvironmentVariables.cs | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
index 5b0a5a8bd..e526fb85a 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs
@@ -16,7 +16,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
{
if (_envStringPaths == null)
{
- _envStringPaths = LoadEnvironmentStringPaths();
+ LoadEnvironmentStringPaths();
}
return _envStringPaths;
}
@@ -40,9 +40,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search
dir.Split('%').Length == 3);
}
- internal static Dictionary LoadEnvironmentStringPaths()
+ private static void LoadEnvironmentStringPaths()
{
- var envStringPaths = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
+ _envStringPaths = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
var homedrive = Environment.GetEnvironmentVariable("HOMEDRIVE")?.EnsureTrailingSlash() ?? "C:\\";
foreach (DictionaryEntry special in Environment.GetEnvironmentVariables())
@@ -61,11 +61,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search
{
// Variables are returned with a mixture of all upper/lower case.
// Call ToUpper() to make the results look consistent
- envStringPaths.Add(special.Key.ToString().ToUpper(), path);
+ _envStringPaths.Add(special.Key.ToString().ToUpper(), path);
}
}
-
- return envStringPaths;
}
internal static List GetEnvironmentStringPathSuggestions(string querySearch, Query query, PluginInitContext context)
From b739bb49d307e3d1d058bd3504e43139e260bbf3 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Fri, 20 Jan 2023 15:36:14 +0800
Subject: [PATCH 75/79] Fix CI test failure
---
Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
index 42a0e0c73..a6cf0755c 100644
--- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
+++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
@@ -254,7 +254,7 @@ namespace Flow.Launcher.Plugin.SharedCommands
///
public static bool PathContains(string parentPath, string subPath, bool allowEqual = false)
{
- var rel = Path.GetRelativePath(parentPath, subPath);
+ var rel = Path.GetRelativePath(parentPath.EnsureTrailingSlash(), subPath);
return (rel != "." || allowEqual)
&& rel != ".."
&& !rel.StartsWith("../")
From f31d21a7a42624412620d662efedf2cfeef5c837 Mon Sep 17 00:00:00 2001
From: DB p
Date: Sat, 21 Jan 2023 15:05:12 +0900
Subject: [PATCH 76/79] Add Maximum/Minimum Value with numberbox
---
Flow.Launcher/PriorityChangeWindow.xaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Flow.Launcher/PriorityChangeWindow.xaml b/Flow.Launcher/PriorityChangeWindow.xaml
index d6aadead9..c917eeffc 100644
--- a/Flow.Launcher/PriorityChangeWindow.xaml
+++ b/Flow.Launcher/PriorityChangeWindow.xaml
@@ -85,6 +85,8 @@
Date: Sat, 21 Jan 2023 16:57:41 +0800
Subject: [PATCH 77/79] Return empty when operation canceled
---
Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 83057ff04..51c4c3d9d 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -111,7 +111,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
}
catch (OperationCanceledException)
{
- return results.ToList();
+ return new List();
}
catch (EngineNotAvailableException)
{
From babffe907f2a320b6e05bfe798c32d07d96c71d2 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Sun, 22 Jan 2023 12:59:32 +0800
Subject: [PATCH 78/79] Disable unused import warning
---
Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
index a6cf0755c..cfcaaa44d 100644
--- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
+++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
@@ -1,9 +1,9 @@
using System;
using System.Diagnostics;
using System.IO;
-#if !DEBUG
+#pragma warning disable IDE0005
using System.Windows;
-#endif
+#pragma warning restore IDE0005
namespace Flow.Launcher.Plugin.SharedCommands
{
From dd02ad37bc2a620b3493614b649cbd386e7a3276 Mon Sep 17 00:00:00 2001
From: Vic <10308169+VictoriousRaptor@users.noreply.github.com>
Date: Sun, 22 Jan 2023 13:21:53 +0800
Subject: [PATCH 79/79] Refactor
---
Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
index cfcaaa44d..bd8d32ff5 100644
--- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
+++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
@@ -208,22 +208,16 @@ namespace Flow.Launcher.Plugin.SharedCommands
///
public static string GetPreviousExistingDirectory(Func locationExists, string path)
{
- var previousDirectoryPath = "";
var index = path.LastIndexOf('\\');
if (index > 0 && index < (path.Length - 1))
{
- previousDirectoryPath = path.Substring(0, index + 1);
- if (!locationExists(previousDirectoryPath))
- {
- return "";
- }
+ string previousDirectoryPath = path.Substring(0, index + 1);
+ return locationExists(previousDirectoryPath) ? previousDirectoryPath : "";
}
else
{
return "";
}
-
- return previousDirectoryPath;
}
///