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 0001/2008] 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 0002/2008] 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 0003/2008] 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 0004/2008] 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 0005/2008] 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 b40c1f86245fe051323bb202275a774dd9b3b6ad Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Sat, 12 Feb 2022 17:29:19 -0600 Subject: [PATCH 0006/2008] Reselect to Main Query window when show up --- Flow.Launcher/ViewModel/MainViewModel.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 0fe3bdf80..e92867019 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -774,6 +774,8 @@ namespace Flow.Launcher.ViewModel { MainWindowVisibility = Visibility.Visible; + SelectedResults = Results; + MainWindowVisibilityStatus = true; MainWindowOpacity = 1; From b5b202fe8884f33ed6484bacf6144768666452e6 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Sat, 12 Feb 2022 18:06:45 -0600 Subject: [PATCH 0007/2008] Revert to results panel before hiding when executing context menu --- Flow.Launcher/ViewModel/MainViewModel.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index e92867019..8a3b99801 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -211,11 +211,6 @@ namespace Flow.Launcher.ViewModel SpecialKeyState = GlobalHotkey.CheckModifiers() }); - if (hideWindow) - { - Hide(); - } - if (SelectedIsFromQueryResults()) { _userSelectedRecord.Add(result); @@ -225,6 +220,11 @@ namespace Flow.Launcher.ViewModel { SelectedResults = Results; } + + if (hideWindow) + { + Hide(); + } } }); @@ -772,10 +772,10 @@ namespace Flow.Launcher.ViewModel public void Show() { - MainWindowVisibility = Visibility.Visible; - SelectedResults = Results; + MainWindowVisibility = Visibility.Visible; + MainWindowVisibilityStatus = true; MainWindowOpacity = 1; From 6fdff2971c99f5c4b17bf339653406eadd66b827 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Fri, 25 Mar 2022 16:19:00 -0500 Subject: [PATCH 0008/2008] Merge Explorer & Everything Plugins (Step 1) 1. Shared Interface for Windows Index and Everything Index 2. Settings Merge (Part 1) 3. Include Everything dll --- .../EverythingSDK/Everything64.dll | Bin 0 -> 93000 bytes .../EverythingSDK/Everything86.dll | Bin 0 -> 85320 bytes .../Flow.Launcher.Plugin.Explorer.csproj | 3 + Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 6 +- .../Search/Everything/EverythingAPI.cs | 193 ++++++++++++++++++ .../Everything/EverythingApiDllImport.cs | 153 ++++++++++++++ .../Everything/EverythingSearchManager.cs | 27 +++ .../Search/Everything/SortOption.cs | 39 ++++ .../Search/IPathEnumerable.cs | 9 + .../Search/ResultManager.cs | 24 ++- .../Search/SearchManager.cs | 77 ++----- .../Search/SearchResult.cs | 14 ++ .../Search/WindowsIndex/IIndexProvider.cs | 13 ++ .../{IndexSearch.cs => WindowsIndex.cs} | 72 +++---- .../WindowsIndex/WindowsIndexManager.cs | 70 +++++++ .../Flow.Launcher.Plugin.Explorer/Settings.cs | 41 ++++ .../ViewModels/SettingsViewModel.cs | 4 +- .../Views/ExplorerSettings.xaml | 19 +- .../Views/ExplorerSettings.xaml.cs | 4 +- 19 files changed, 642 insertions(+), 126 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/Everything64.dll create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/Everything86.dll create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/SortOption.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchResult.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs rename Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/{IndexSearch.cs => WindowsIndex.cs} (71%) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexManager.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/Everything64.dll b/Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/Everything64.dll new file mode 100644 index 0000000000000000000000000000000000000000..6d093b79316c04a8b3ff7db50a1a3e37d6c81425 GIT binary patch literal 93000 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 literal 0 HcmV?d00001 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/Everything86.dll b/Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/Everything86.dll new file mode 100644 index 0000000000000000000000000000000000000000..de73b87d109a74e490b57434abc5f413906152aa GIT binary patch literal 85320 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 literal 0 HcmV?d00001 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj index b4ab89a36..ae48ac3ee 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -35,6 +35,9 @@ Designer PreserveNewest + + PreserveNewest + diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index 60208759e..d8879a4f6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -1,9 +1,12 @@ using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Plugin.Explorer.Search; +using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; using Flow.Launcher.Plugin.Explorer.ViewModels; using Flow.Launcher.Plugin.Explorer.Views; +using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -47,7 +50,8 @@ namespace Flow.Launcher.Plugin.Explorer contextMenu = new ContextMenu(Context, Settings, viewModel); searchManager = new SearchManager(Settings, Context); ResultManager.Init(Context, Settings); - + EverythingApiDllImport.Load(Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", + Environment.Is64BitProcess ? "Everything64.dll" : "Everything86.dll")); return Task.CompletedTask; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs new file mode 100644 index 000000000..089a0f8ff --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -0,0 +1,193 @@ +using Flow.Launcher.Plugin.Everything.Everything; +using Flow.Launcher.Plugin.Everything.Everything.Exceptions; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + + public static class EverythingApi + { + + private const int BufferSize = 4096; + + private static readonly object syncObject = new object(); + // cached buffer to remove redundant allocations. + private static readonly StringBuilder buffer = new StringBuilder(BufferSize); + + public enum StateCode + { + OK, + MemoryError, + IPCError, + RegisterClassExError, + CreateWindowError, + CreateThreadError, + InvalidIndexError, + InvalidCallError + } + + /// + /// Gets or sets a value indicating whether [match path]. + /// + /// true if [match path]; otherwise, false. + public static bool MatchPath + { + get => EverythingApiDllImport.Everything_GetMatchPath(); + set => EverythingApiDllImport.Everything_SetMatchPath(value); + } + + /// + /// Gets or sets a value indicating whether [match case]. + /// + /// true if [match case]; otherwise, false. + public static bool MatchCase + { + get => EverythingApiDllImport.Everything_GetMatchCase(); + set => EverythingApiDllImport.Everything_SetMatchCase(value); + } + + /// + /// Gets or sets a value indicating whether [match whole word]. + /// + /// true if [match whole word]; otherwise, false. + public static bool MatchWholeWord + { + get => EverythingApiDllImport.Everything_GetMatchWholeWord(); + set => EverythingApiDllImport.Everything_SetMatchWholeWord(value); + } + + /// + /// Gets or sets a value indicating whether [enable regex]. + /// + /// true if [enable regex]; otherwise, false. + public static bool EnableRegex + { + get => EverythingApiDllImport.Everything_GetRegex(); + set => EverythingApiDllImport.Everything_SetRegex(value); + } + + /// + /// Resets this instance. + /// + private static void Reset() + { + lock (syncObject) + { + EverythingApiDllImport.Everything_Reset(); + } + } + + /// + /// Checks whether the sort option is Fast Sort. + /// + public static bool IsFastSortOption(SortOption sortOption) + { + var fastSortOptionEnabled = EverythingApiDllImport.Everything_IsFastSort(sortOption); + + // If the Everything service is not running, then this call will incorrectly report + // the state as false. This checks for errors thrown by the api and up to the caller to handle. + CheckAndThrowExceptionOnError(); + + return fastSortOptionEnabled; + } + + /// + /// Searches the specified key word and reset the everything API afterwards + /// + /// The key word. + /// when cancelled the current search will stop and exit (and would not reset) + /// Sort By + /// The offset. + /// The max count. + /// + public static IEnumerable SearchAsync(string keyword, CancellationToken token, SortOption sortOption = SortOption.NAME_ASCENDING, int offset = 0, int maxCount = 100) + { + if (string.IsNullOrEmpty(keyword)) + throw new ArgumentNullException(nameof(keyword)); + + if (offset < 0) + throw new ArgumentOutOfRangeException(nameof(offset)); + + if (maxCount < 0) + throw new ArgumentOutOfRangeException(nameof(maxCount)); + + lock (syncObject) + { + if (keyword.StartsWith("@")) + { + EverythingApiDllImport.Everything_SetRegex(true); + keyword = keyword[1..]; + } + + EverythingApiDllImport.Everything_SetSearchW(keyword); + EverythingApiDllImport.Everything_SetOffset(offset); + EverythingApiDllImport.Everything_SetMax(maxCount); + + EverythingApiDllImport.Everything_SetSort(sortOption); + + if (token.IsCancellationRequested) + { + return null; + } + + + if (!EverythingApiDllImport.Everything_QueryW(true)) + { + CheckAndThrowExceptionOnError(); + return null; + } + + var results = new List(); + for (var idx = 0; idx < EverythingApiDllImport.Everything_GetNumResults(); ++idx) + { + if (token.IsCancellationRequested) + { + return null; + } + + EverythingApiDllImport.Everything_GetResultFullPathNameW(idx, buffer, BufferSize); + + var result = new SearchResult + { + FullPath = buffer.ToString(), + Type = EverythingApiDllImport.Everything_IsFolderResult(idx) ? ResultType.Folder : + EverythingApiDllImport.Everything_IsFileResult(idx) ? ResultType.File : + ResultType.Volume + }; + + results.Add(result); + } + + Reset(); + + return results; + } + } + + private static void CheckAndThrowExceptionOnError() + { + switch (EverythingApiDllImport.Everything_GetLastError()) + { + case StateCode.CreateThreadError: + throw new CreateThreadException(); + case StateCode.CreateWindowError: + throw new CreateWindowException(); + case StateCode.InvalidCallError: + throw new InvalidCallException(); + case StateCode.InvalidIndexError: + throw new InvalidIndexException(); + case StateCode.IPCError: + throw new IPCErrorException(); + case StateCode.MemoryError: + throw new MemoryErrorException(); + case StateCode.RegisterClassExError: + throw new RegisterClassExException(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs new file mode 100644 index 000000000..b100a6026 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs @@ -0,0 +1,153 @@ +using Flow.Launcher.Plugin.Everything.Everything; +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + public static class EverythingApiDllImport + { + public static void Load(string path) + { + LoadLibrary(path); + } + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + private static extern int LoadLibrary(string name); + + private const string DLL = "Everything.dll"; + + [DllImport(DLL, CharSet = CharSet.Unicode)] + internal static extern int Everything_SetSearchW(string lpSearchString); + + [DllImport(DLL)] + internal static extern void Everything_SetMatchPath(bool bEnable); + + [DllImport(DLL)] + internal static extern void Everything_SetMatchCase(bool bEnable); + + [DllImport(DLL)] + internal static extern void Everything_SetMatchWholeWord(bool bEnable); + + [DllImport(DLL)] + internal static extern void Everything_SetRegex(bool bEnable); + + [DllImport(DLL)] + internal static extern void Everything_SetMax(int dwMax); + + [DllImport(DLL)] + internal static extern void Everything_SetOffset(int dwOffset); + + [DllImport(DLL)] + internal static extern bool Everything_GetMatchPath(); + + [DllImport(DLL)] + internal static extern bool Everything_GetMatchCase(); + + [DllImport(DLL)] + internal static extern bool Everything_GetMatchWholeWord(); + + [DllImport(DLL)] + internal static extern bool Everything_GetRegex(); + + [DllImport(DLL)] + internal static extern uint Everything_GetMax(); + + [DllImport(DLL)] + internal static extern uint Everything_GetOffset(); + + [DllImport(DLL, CharSet = CharSet.Unicode)] + internal static extern string Everything_GetSearchW(); + + [DllImport(DLL)] + internal static extern EverythingApi.StateCode Everything_GetLastError(); + + [DllImport(DLL, CharSet = CharSet.Unicode)] + internal static extern bool Everything_QueryW(bool bWait); + + [DllImport(DLL)] + internal static extern void Everything_SortResultsByPath(); + + [DllImport(DLL)] + internal static extern int Everything_GetNumFileResults(); + + [DllImport(DLL)] + internal static extern int Everything_GetNumFolderResults(); + + [DllImport(DLL)] + internal static extern int Everything_GetNumResults(); + + [DllImport(DLL)] + internal static extern int Everything_GetTotFileResults(); + + [DllImport(DLL)] + internal static extern int Everything_GetTotFolderResults(); + + [DllImport(DLL)] + internal static extern int Everything_GetTotResults(); + + [DllImport(DLL)] + internal static extern bool Everything_IsVolumeResult(int nIndex); + + [DllImport(DLL)] + internal static extern bool Everything_IsFolderResult(int nIndex); + + [DllImport(DLL)] + internal static extern bool Everything_IsFileResult(int nIndex); + + [DllImport(DLL, CharSet = CharSet.Unicode)] + internal static extern void Everything_GetResultFullPathNameW(int nIndex, StringBuilder lpString, int nMaxCount); + + [DllImport(DLL)] + internal static extern void Everything_Reset(); + + // Everything 1.4 + + [DllImport(DLL)] + public static extern void Everything_SetSort(SortOption dwSortType); + [DllImport(DLL)] + public static extern bool Everything_IsFastSort(SortOption dwSortType); + [DllImport(DLL)] + public static extern SortOption Everything_GetSort(); + [DllImport(DLL)] + public static extern uint Everything_GetResultListSort(); + [DllImport(DLL)] + public static extern void Everything_SetRequestFlags(uint dwRequestFlags); + [DllImport(DLL)] + public static extern uint Everything_GetRequestFlags(); + [DllImport(DLL)] + public static extern uint Everything_GetResultListRequestFlags(); + [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] + public static extern IntPtr Everything_GetResultExtension(uint nIndex); + [DllImport(DLL)] + public static extern bool Everything_GetResultSize(uint nIndex, out long lpFileSize); + [DllImport(DLL)] + public static extern bool Everything_GetResultDateCreated(uint nIndex, out long lpFileTime); + [DllImport(DLL)] + public static extern bool Everything_GetResultDateModified(uint nIndex, out long lpFileTime); + [DllImport(DLL)] + public static extern bool Everything_GetResultDateAccessed(uint nIndex, out long lpFileTime); + [DllImport(DLL)] + public static extern uint Everything_GetResultAttributes(uint nIndex); + [DllImport(DLL, CharSet = CharSet.Unicode)] + public static extern IntPtr Everything_GetResultFileListFileName(uint nIndex); + [DllImport(DLL)] + public static extern uint Everything_GetResultRunCount(uint nIndex); + [DllImport(DLL)] + public static extern bool Everything_GetResultDateRun(uint nIndex, out long lpFileTime); + [DllImport(DLL)] + public static extern bool Everything_GetResultDateRecentlyChanged(uint nIndex, out long lpFileTime); + [DllImport(DLL, CharSet = CharSet.Unicode)] + public static extern IntPtr Everything_GetResultHighlightedFileName(uint nIndex); + [DllImport(DLL, CharSet = CharSet.Unicode)] + public static extern IntPtr Everything_GetResultHighlightedPath(uint nIndex); + [DllImport(DLL, CharSet = CharSet.Unicode)] + public static extern IntPtr Everything_GetResultHighlightedFullPathAndFileName(uint nIndex); + [DllImport(DLL)] + public static extern uint Everything_GetRunCountFromFileName(string lpFileName); + [DllImport(DLL)] + public static extern bool Everything_SetRunCountFromFileName(string lpFileName, uint dwRunCount); + [DllImport(DLL)] + public static extern uint Everything_IncRunCountFromFileName(string lpFileName); + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs new file mode 100644 index 000000000..e1486f9fb --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -0,0 +1,27 @@ +using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + public class EverythingSearchManager : IIndexProvider + { + private Settings Settings { get; } + + public EverythingSearchManager(Settings settings) + { + Settings = settings; + } + + + public ValueTask> SearchAsync(Query query, CancellationToken token) + { + return ValueTask.FromResult(EverythingApi.SearchAsync(query.Search, token, Settings.SortOption)); + } + public ValueTask> ContentSearchAsync(Query query, CancellationToken token) + { + return new ValueTask>(new List()); + } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/SortOption.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/SortOption.cs new file mode 100644 index 000000000..434afd1b4 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/SortOption.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Flow.Launcher.Plugin.Everything.Everything +{ + public enum SortOption : uint + { + NAME_ASCENDING = 1u, + NAME_DESCENDING = 2u, + PATH_ASCENDING = 3u, + PATH_DESCENDING = 4u, + SIZE_ASCENDING = 5u, + SIZE_DESCENDING = 6u, + EXTENSION_ASCENDING = 7u, + EXTENSION_DESCENDING = 8u, + TYPE_NAME_ASCENDING = 9u, + TYPE_NAME_DESCENDING = 10u, + DATE_CREATED_ASCENDING = 11u, + DATE_CREATED_DESCENDING = 12u, + DATE_MODIFIED_ASCENDING = 13u, + DATE_MODIFIED_DESCENDING = 14u, + ATTRIBUTES_ASCENDING = 15u, + ATTRIBUTES_DESCENDING = 16u, + FILE_LIST_FILENAME_ASCENDING = 17u, + FILE_LIST_FILENAME_DESCENDING = 18u, + RUN_COUNT_ASCENDING = 19u, + RUN_COUNT_DESCENDING = 20u, + DATE_RECENTLY_CHANGED_ASCENDING = 21u, + DATE_RECENTLY_CHANGED_DESCENDING = 22u, + DATE_ACCESSED_ASCENDING = 23u, + DATE_ACCESSED_DESCENDING = 24u, + DATE_RUN_ASCENDING = 25u, + DATE_RUN_DESCENDING = 26u + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs new file mode 100644 index 000000000..d7f0a8ec8 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Flow.Launcher.Plugin.Explorer.Search +{ + public interface IPathEnumerable + { + public IEnumerable Enumerate(string path, bool recursive); + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs index 63310bebd..35ba0bafb 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs @@ -35,6 +35,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search return $"{keyword}{formatted_path}"; } + public static Result CreateResult(Query query, SearchResult result) + { + return result.Type switch + { + ResultType.Folder or ResultType.Volume => CreateFolderResult(Path.GetFileName(result.FullPath), + result.FullPath, result.FullPath, query, 0, result.ShowIndexState, result.WindowsIndexed), + ResultType.File => CreateFileResult( + result.FullPath, query, 0, result.ShowIndexState, result.WindowsIndexed), + _ => throw new ArgumentOutOfRangeException() + }; + } + internal static Result CreateFolderResult(string title, string subtitle, string path, Query query, int score = 0, bool showIndexState = false, bool windowsIndexed = false) { return new Result @@ -61,7 +73,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search } Context.API.ChangeQuery(GetPathWithActionKeyword(path, ResultType.Folder)); - + return false; }, Score = score, @@ -192,16 +204,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search } } - internal class SearchResult - { - public string FullPath { get; set; } - public ResultType Type { get; set; } - - public bool WindowsIndexed { get; set; } - - public bool ShowIndexState { get; set; } - } - public enum ResultType { Volume, diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 8ce627a44..080621f42 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -57,8 +57,16 @@ namespace Flow.Launcher.Plugin.Explorer.Search results.UnionWith(quickaccessLinks); } + IEnumerable searchResults; + if (IsFileContentSearch(query.ActionKeyword)) - return await WindowsIndexFileContentSearchAsync(query, querySearch, token).ConfigureAwait(false); + { + searchResults = await Settings.IndexProvider.ContentSearchAsync(query, token); + } + else + { + searchResults = await Settings.IndexProvider.SearchAsync(query, token); + } if (ActionKeywordMatch(query, Settings.ActionKeyword.PathSearchActionKeyword) || ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword)) @@ -71,8 +79,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search querySearch.Length > 0 && !querySearch.IsLocationPathString()) { - results.UnionWith(await WindowsIndexFilesAndFoldersSearchAsync(query, querySearch, token) - .ConfigureAwait(false)); + if (searchResults != null) + results.UnionWith(searchResults.Select(search => ResultManager.CreateResult(query, search))); } return results.ToList(); @@ -93,7 +101,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search Settings.ActionKeyword.IndexSearchActionKeyword => Settings.IndexSearchKeywordEnabled && keyword == Settings.IndexSearchActionKeyword, Settings.ActionKeyword.QuickAccessActionKeyword => Settings.QuickAccessKeywordEnabled && - keyword == Settings.QuickAccessActionKeyword + keyword == Settings.QuickAccessActionKeyword }; } @@ -126,37 +134,20 @@ namespace Flow.Launcher.Plugin.Explorer.Search token.ThrowIfCancellationRequested(); - var directoryResult = await TopLevelDirectorySearchBehaviourAsync(WindowsIndexTopLevelFolderSearchAsync, - DirectoryInfoClassSearch, - useIndexSearch, - query, - locationPath, - token).ConfigureAwait(false); + // var directoryResult = await TopLevelDirectorySearchBehaviourAsync(WindowsIndexTopLevelFolderSearchAsync, + // DirectoryInfoClassSearch, + // useIndexSearch, + // query, + // locationPath, + // token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); - results.UnionWith(directoryResult); + // results.UnionWith(directoryResult); return results.ToList(); } - private async Task> WindowsIndexFileContentSearchAsync(Query query, string querySearchString, - CancellationToken token) - { - var queryConstructor = new QueryConstructor(Settings); - - if (string.IsNullOrEmpty(querySearchString)) - return new List(); - - return await IndexSearch.WindowsIndexSearchAsync( - querySearchString, - queryConstructor.CreateQueryHelper, - queryConstructor.QueryForFileContentSearch, - Settings.IndexSearchExcludedSubdirectoryPaths, - query, - token).ConfigureAwait(false); - } - public bool IsFileContentSearch(string actionKeyword) { return actionKeyword == Settings.FileContentSearchActionKeyword; @@ -181,34 +172,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search return await windowsIndexSearch(query, querySearchString, token); } - private async Task> WindowsIndexFilesAndFoldersSearchAsync(Query query, string querySearchString, - CancellationToken token) - { - var queryConstructor = new QueryConstructor(Settings); - - return await IndexSearch.WindowsIndexSearchAsync( - querySearchString, - queryConstructor.CreateQueryHelper, - queryConstructor.QueryForAllFilesAndFolders, - Settings.IndexSearchExcludedSubdirectoryPaths, - query, - token).ConfigureAwait(false); - } - - private async Task> WindowsIndexTopLevelFolderSearchAsync(Query query, string path, - CancellationToken token) - { - var queryConstructor = new QueryConstructor(Settings); - - return await IndexSearch.WindowsIndexSearchAsync( - path, - queryConstructor.CreateQueryHelper, - queryConstructor.QueryForTopLevelDirectorySearch, - Settings.IndexSearchExcludedSubdirectoryPaths, - query, - token).ConfigureAwait(false); - } - private bool UseWindowsIndexForDirectorySearch(string locationPath) { var pathToDirectory = FilesFolders.ReturnPreviousDirectoryIfIncompleteString(locationPath); @@ -221,7 +184,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search .StartsWith(x.Path, StringComparison.OrdinalIgnoreCase))) return false; - return IndexSearch.PathIsIndexed(pathToDirectory); + return WindowsIndex.WindowsIndex.PathIsIndexed(pathToDirectory); } } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchResult.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchResult.cs new file mode 100644 index 000000000..815c6b7b0 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchResult.cs @@ -0,0 +1,14 @@ +using System; + +namespace Flow.Launcher.Plugin.Explorer.Search +{ + public struct SearchResult + { + public string FullPath { get; init; } + public ResultType Type { get; init; } + + public bool WindowsIndexed { get; init; } + + public bool ShowIndexState { get; init; } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs new file mode 100644 index 000000000..e42d78f9a --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs @@ -0,0 +1,13 @@ +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex +{ + public interface IIndexProvider + { + public ValueTask> SearchAsync(Query query, CancellationToken token); + public ValueTask> ContentSearchAsync(Query query, CancellationToken token); + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs similarity index 71% rename from Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs rename to Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs index 2e842c843..28e9c0e71 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs @@ -13,16 +13,15 @@ using System.Windows; namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex { - internal static class IndexSearch + internal static class WindowsIndex { // Reserved keywords in oleDB - private const string reservedStringPattern = @"^[`\@\#\^,\&\/\\\$\%_;\[\]]+$"; + private const string ReservedStringPattern = @"^[`\@\#\^,\&\/\\\$\%_;\[\]]+$"; - internal static async Task> ExecuteWindowsIndexSearchAsync(string indexQueryString, string connectionString, Query query, CancellationToken token) + private static async Task> ExecuteWindowsIndexSearchAsync(string indexQueryString, string connectionString, Query query, CancellationToken token) { - var results = new List(); - var fileResults = new List(); + var results = new List(); try { @@ -35,7 +34,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex await using var dataReaderResults = await command.ExecuteReaderAsync(token) as OleDbDataReader; token.ThrowIfCancellationRequested(); - if (dataReaderResults.HasRows) + if (dataReaderResults is { HasRows: true }) { while (await dataReaderResults.ReadAsync(token)) { @@ -49,18 +48,12 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex var path = new Uri(encodedFragmentPath).LocalPath; - if (dataReaderResults.GetString(2) == "Directory") + results.Add(new SearchResult() { - results.Add(ResultManager.CreateFolderResult( - dataReaderResults.GetString(0), - path, - path, - query, 0, true, true)); - } - else - { - fileResults.Add(ResultManager.CreateFileResult(path, query, 0, true, true)); - } + FullPath = path, + Type = dataReaderResults.GetString(2) == "Directory" ? ResultType.Folder : ResultType.File, + WindowsIndexed = true + }); } } } @@ -80,13 +73,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex LogException("General error from performing index search", e); } - results.AddRange(fileResults); - - // Intial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection. - return results; + // Initial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection. + return results; } - internal async static Task> WindowsIndexSearchAsync( + internal static async ValueTask> WindowsIndexSearchAsync( string searchString, Func createQueryHelper, Func constructQuery, @@ -94,28 +85,15 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex Query query, CancellationToken token) { - var regexMatch = Regex.Match(searchString, reservedStringPattern); + var regexMatch = Regex.Match(searchString, ReservedStringPattern); if (regexMatch.Success) - return new List(); - - try - { - var constructedQuery = constructQuery(searchString); + return new(); - return RemoveResultsInExclusionList( - await ExecuteWindowsIndexSearchAsync(constructedQuery, createQueryHelper().ConnectionString, query, token).ConfigureAwait(false), - exclusionList, - token); - } - catch (COMException) - { - // Occurs because the Windows Indexing (WSearch) is turned off in services and unable to be used by Explorer plugin - if (!SearchManager.Settings.WarnWindowsSearchServiceOff) - return new List(); + var constructedQuery = constructQuery(searchString); - return ResultForWindexSearchOff(query.RawQuery); - } + return + await ExecuteWindowsIndexSearchAsync(constructedQuery, createQueryHelper().ConnectionString, query, token); } private static List RemoveResultsInExclusionList(List results, List exclusionList, CancellationToken token) @@ -159,7 +137,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex var indexManager = csm.GetCatalog("SystemIndex").GetCrawlScopeManager(); return indexManager.IncludedInCrawlScope(path) > 0; } - catch(COMException) + catch (COMException) { // Occurs because the Windows Indexing (WSearch) is turned off in services and unable to be used by Explorer plugin return false; @@ -180,18 +158,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex { SearchManager.Settings.WarnWindowsSearchServiceOff = false; - var pluginsManagerPlugin= api.GetAllPlugins().FirstOrDefault(x => x.Metadata.ID == "9f8f9b14-2518-4907-b211-35ab6290dee7"); + var pluginsManagerPlugin = api.GetAllPlugins().FirstOrDefault(x => x.Metadata.ID == "9f8f9b14-2518-4907-b211-35ab6290dee7"); var actionKeywordCount = pluginsManagerPlugin.Metadata.ActionKeywords.Count; if (actionKeywordCount > 1) LogException("PluginsManager's action keyword has increased to more than 1, this does not allow for determining the " + - "right action keyword. Explorer's code for managing Windows Search service not running exception needs to be updated", + "right action keyword. Explorer's code for managing Windows Search service not running exception needs to be updated", new InvalidOperationException()); if (MessageBox.Show(string.Format(api.GetTranslation("plugin_explorer_alternative"), Environment.NewLine), - api.GetTranslation("plugin_explorer_alternative_title"), - MessageBoxButton.YesNo) == MessageBoxResult.Yes + api.GetTranslation("plugin_explorer_alternative_title"), + MessageBoxButton.YesNo) == MessageBoxResult.Yes && actionKeywordCount == 1) { api.ChangeQuery(string.Format("{0} install everything", pluginsManagerPlugin.Metadata.ActionKeywords[0])); @@ -221,7 +199,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex throw e; #else Log.Exception($"|Flow.Launcher.Plugin.Explorer.IndexSearch|{message}", e); -#endif +#endif } } -} +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexManager.cs new file mode 100644 index 000000000..72f5e9cb1 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexManager.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex +{ + public class WindowsIndexManager : IIndexProvider + { + private Settings Settings { get; } + private QueryConstructor QueryConstructor { get; } + public WindowsIndexManager(Settings settings) + { + Settings = settings; + QueryConstructor = new QueryConstructor(Settings); + } + + + private async Task> WindowsIndexFileContentSearchAsync(Query query, string querySearchString, + CancellationToken token) + { + if (string.IsNullOrEmpty(querySearchString)) + return new List(); + + return await WindowsIndex.WindowsIndexSearchAsync( + querySearchString, + QueryConstructor.CreateQueryHelper, + QueryConstructor.QueryForFileContentSearch, + Settings.IndexSearchExcludedSubdirectoryPaths, + query, + token).ConfigureAwait(false); + } + + + + private async Task> WindowsIndexFilesAndFoldersSearchAsync(Query query, string querySearchString, + CancellationToken token) + { + return await WindowsIndex.WindowsIndexSearchAsync( + querySearchString, + QueryConstructor.CreateQueryHelper, + QueryConstructor.QueryForAllFilesAndFolders, + Settings.IndexSearchExcludedSubdirectoryPaths, + query, + token).ConfigureAwait(false); + } + + + private async Task> WindowsIndexTopLevelFolderSearchAsync(Query query, string path, + CancellationToken token) + { + var queryConstructor = new QueryConstructor(Settings); + + return await WindowsIndex.WindowsIndexSearchAsync( + path, + queryConstructor.CreateQueryHelper, + queryConstructor.QueryForTopLevelDirectorySearch, + Settings.IndexSearchExcludedSubdirectoryPaths, + query, + token).ConfigureAwait(false); + } + public ValueTask> SearchAsync(Query query, CancellationToken token) + { + return default; + } + public ValueTask> ContentSearchAsync(Query query, CancellationToken token) + { + return default; + } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 351091dfe..f3ce8abc5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -1,7 +1,11 @@ +using Flow.Launcher.Plugin.Everything.Everything; using Flow.Launcher.Plugin.Explorer.Search; +using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; +using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; using System; using System.Collections.Generic; +using System.Linq; namespace Flow.Launcher.Plugin.Explorer { @@ -40,6 +44,43 @@ namespace Flow.Launcher.Plugin.Explorer public bool WarnWindowsSearchServiceOff { get; set; } = true; + private List _indexProviders; + public Settings() + { + _indexProviders = new List() + { + new EverythingSearchManager(this), + new WindowsIndexManager(this) + }; + } + public IndexSearchEngineOption IndexSearchEngine { get; set; } + public IIndexProvider IndexProvider => _indexProviders[(int)IndexSearchEngine]; + + public enum PathTraversalEngineOption + { + Everything, + WindowsIndex, + Direct + } + + public enum IndexSearchEngineOption + { + Everything, + WindowsIndex + } + #region Everything Settings + + + public bool LaunchHidden { get; set; } = false; + + public string EverythingInstalledPath { get; set; } + + public SortOption[] SortOptions { get; set; } = Enum.GetValues(); + + public SortOption SortOption { get; set; } = SortOption.NAME_ASCENDING; + + #endregion + internal enum ActionKeyword { SearchActionKeyword, diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 77ec5457b..e1793ad47 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -9,7 +9,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels { public class SettingsViewModel { - internal Settings Settings { get; set; } + public Settings Settings { get; set; } internal PluginInitContext Context { get; set; } @@ -29,7 +29,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels internal void RemoveAccessLinkFromExcludedIndexPaths(AccessLink selectedRow) => Settings.IndexSearchExcludedSubdirectoryPaths.Remove(selectedRow); - internal void OpenWindowsIndexingOptions() + internal static void OpenWindowsIndexingOptions() { var psi = new ProcessStartInfo { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index a7fa58643..a441c10b5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -6,14 +6,13 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:viewModels="clr-namespace:Flow.Launcher.Plugin.Explorer.ViewModels" xmlns:views="clr-namespace:Flow.Launcher.Plugin.Explorer.Views" + xmlns:qa="clr-namespace:Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks" d:DesignHeight="450" d:DesignWidth="800" - mc:Ignorable="d"> + mc:Ignorable="d" + d:DataContext="{d:DesignInstance viewModels:SettingsViewModel}"> - - - - + @@ -97,8 +96,14 @@ AllowDrop="True" DragEnter="lbxAccessLinks_DragEnter" Drop="lbxAccessLinks_Drop" - ItemTemplate="{StaticResource ListViewTemplateExcludedPaths}" /> + ItemTemplate="{StaticResource ListViewActionKeywords}" /> + + @@ -144,4 +149,4 @@ - + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml.cs index 63c4a8dca..8f60d0178 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml.cs @@ -25,6 +25,8 @@ namespace Flow.Launcher.Plugin.Explorer.Views public ExplorerSettings(SettingsViewModel viewModel) { + DataContext = viewModel; + InitializeComponent(); this.viewModel = viewModel; @@ -310,7 +312,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views private void btnOpenIndexingOptions_Click(object sender, RoutedEventArgs e) { - viewModel.OpenWindowsIndexingOptions(); + SettingsViewModel.OpenWindowsIndexingOptions(); } public void SetButtonVisibilityToHidden() From b671f562effc409ab730a7b1bb0983b520979b57 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Fri, 25 Mar 2022 16:33:01 -0500 Subject: [PATCH 0009/2008] Add missing File --- .../Search/Everything/EverythingAPI.cs | 2 +- .../Everything/Exceptions/CreateThreadException.cs | 11 +++++++++++ .../Everything/Exceptions/CreateWindowException.cs | 11 +++++++++++ .../Search/Everything/Exceptions/IPCErrorException.cs | 11 +++++++++++ .../Everything/Exceptions/InvalidCallException.cs | 11 +++++++++++ .../Everything/Exceptions/InvalidIndexException.cs | 11 +++++++++++ .../Everything/Exceptions/MemoryErrorException.cs | 11 +++++++++++ .../Everything/Exceptions/RegisterClassExException.cs | 11 +++++++++++ 8 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/CreateThreadException.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/CreateWindowException.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/IPCErrorException.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/InvalidCallException.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/InvalidIndexException.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/MemoryErrorException.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/RegisterClassExException.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 089a0f8ff..838d05dd3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -1,5 +1,5 @@ using Flow.Launcher.Plugin.Everything.Everything; -using Flow.Launcher.Plugin.Everything.Everything.Exceptions; +using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; using System; using System.Collections.Generic; using System.Runtime.InteropServices; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/CreateThreadException.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/CreateThreadException.cs new file mode 100644 index 000000000..32163057b --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/CreateThreadException.cs @@ -0,0 +1,11 @@ +using System; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions +{ + /// + /// + /// + public class CreateThreadException : ApplicationException + { + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/CreateWindowException.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/CreateWindowException.cs new file mode 100644 index 000000000..9704226d7 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/CreateWindowException.cs @@ -0,0 +1,11 @@ +using System; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions +{ + /// + /// + /// + public class CreateWindowException : ApplicationException + { + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/IPCErrorException.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/IPCErrorException.cs new file mode 100644 index 000000000..41629d2e4 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/IPCErrorException.cs @@ -0,0 +1,11 @@ +using System; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions +{ + /// + /// + /// + public class IPCErrorException : ApplicationException + { + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/InvalidCallException.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/InvalidCallException.cs new file mode 100644 index 000000000..f84dc1ab8 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/InvalidCallException.cs @@ -0,0 +1,11 @@ +using System; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions +{ + /// + /// + /// + public class InvalidCallException : ApplicationException + { + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/InvalidIndexException.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/InvalidIndexException.cs new file mode 100644 index 000000000..cbf75e5a3 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/InvalidIndexException.cs @@ -0,0 +1,11 @@ +using System; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions +{ + /// + /// + /// + public class InvalidIndexException : ApplicationException + { + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/MemoryErrorException.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/MemoryErrorException.cs new file mode 100644 index 000000000..c632cd530 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/MemoryErrorException.cs @@ -0,0 +1,11 @@ +using System; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions +{ + /// + /// + /// + public class MemoryErrorException : ApplicationException + { + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/RegisterClassExException.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/RegisterClassExException.cs new file mode 100644 index 000000000..2ebdbb689 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Exceptions/RegisterClassExException.cs @@ -0,0 +1,11 @@ +using System; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions +{ + /// + /// + /// + public class RegisterClassExException : ApplicationException + { + } +} \ No newline at end of file From fa0cd35e186fe253a3a79e29a4ef44169f6897aa Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Mon, 28 Mar 2022 15:28:18 -0500 Subject: [PATCH 0010/2008] Support Path Enumeration (Part 1) --- .../Search/Everything/EverythingAPI.cs | 18 ++++++-- .../Everything/EverythingSearchManager.cs | 13 ++++-- .../Search/IContentIndexProvider.cs | 11 +++++ .../Search/IIndexProvider.cs | 11 +++++ .../Search/IPathEnumerable.cs | 7 ++- .../Search/SearchManager.cs | 34 ++++++++------- .../Search/WindowsIndex/IIndexProvider.cs | 13 ------ .../Search/WindowsIndex/WindowsIndex.cs | 37 +++------------- ...anager.cs => WindowsIndexSearchManager.cs} | 27 ++++++------ .../Flow.Launcher.Plugin.Explorer/Settings.cs | 43 ++++++++++++++++--- 10 files changed, 129 insertions(+), 85 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/IIndexProvider.cs delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs rename Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/{WindowsIndexManager.cs => WindowsIndexSearchManager.cs} (64%) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 838d05dd3..501ce5b22 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -101,15 +101,20 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything /// /// The key word. /// when cancelled the current search will stop and exit (and would not reset) + /// Search Within a parent folder + /// Search Within sub folder of the parent folder /// Sort By /// The offset. /// The max count. /// - public static IEnumerable SearchAsync(string keyword, CancellationToken token, SortOption sortOption = SortOption.NAME_ASCENDING, int offset = 0, int maxCount = 100) + public static IEnumerable SearchAsync(string keyword, + CancellationToken token, + SortOption sortOption = SortOption.NAME_ASCENDING, + string parentPath = "", + bool recursive = false, + int offset = 0, + int maxCount = 100) { - if (string.IsNullOrEmpty(keyword)) - throw new ArgumentNullException(nameof(keyword)); - if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset)); @@ -124,6 +129,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything keyword = keyword[1..]; } + if (!string.IsNullOrEmpty(parentPath)) + { + keyword += $" {(recursive ? "" : "parent:")}\"{parentPath}\""; + } + EverythingApiDllImport.Everything_SetSearchW(keyword); EverythingApiDllImport.Everything_SetOffset(offset); EverythingApiDllImport.Everything_SetMax(maxCount); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index e1486f9fb..14069f678 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; namespace Flow.Launcher.Plugin.Explorer.Search.Everything { - public class EverythingSearchManager : IIndexProvider + public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IPathEnumerable { private Settings Settings { get; } @@ -15,13 +15,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything } - public ValueTask> SearchAsync(Query query, CancellationToken token) + public ValueTask> SearchAsync(string search, CancellationToken token) { - return ValueTask.FromResult(EverythingApi.SearchAsync(query.Search, token, Settings.SortOption)); + return ValueTask.FromResult(EverythingApi.SearchAsync(search, token, Settings.SortOption)); } - public ValueTask> ContentSearchAsync(Query query, CancellationToken token) + public ValueTask> ContentSearchAsync(string search, CancellationToken token) { return new ValueTask>(new List()); } + public ValueTask> EnumerateAsync(string path, string search, bool recursive, CancellationToken token) + { + return new ValueTask>( + EverythingApi.SearchAsync("", token, Settings.SortOption, path, recursive)); + } } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs new file mode 100644 index 000000000..b2142357e --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Flow.Launcher.Plugin.Explorer.Search +{ + public interface IContentIndexProvider + { + public ValueTask> ContentSearchAsync(string search, CancellationToken token); + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IIndexProvider.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IIndexProvider.cs new file mode 100644 index 000000000..be40b6a24 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IIndexProvider.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Flow.Launcher.Plugin.Explorer.Search +{ + public interface IIndexProvider + { + public ValueTask> SearchAsync(string search, CancellationToken token); + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs index d7f0a8ec8..eb82422f4 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs @@ -1,9 +1,12 @@ -using System.Collections.Generic; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; namespace Flow.Launcher.Plugin.Explorer.Search { public interface IPathEnumerable { - public IEnumerable Enumerate(string path, bool recursive); + public ValueTask> EnumerateAsync(string path, string search, bool recursive, CancellationToken token); } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 080621f42..93707dcf2 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -61,11 +61,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search if (IsFileContentSearch(query.ActionKeyword)) { - searchResults = await Settings.IndexProvider.ContentSearchAsync(query, token); + searchResults = await Settings.ContentIndexProvider.ContentSearchAsync(query.Search, token); } else { - searchResults = await Settings.IndexProvider.SearchAsync(query, token); + searchResults = await Settings.IndexProvider.SearchAsync(query.Search, token); } if (ActionKeywordMatch(query, Settings.ActionKeyword.PathSearchActionKeyword) || @@ -120,12 +120,12 @@ namespace Flow.Launcher.Plugin.Explorer.Search var isEnvironmentVariablePath = querySearch[1..].Contains("%\\"); var locationPath = querySearch; - + if (isEnvironmentVariablePath) locationPath = EnvironmentVariables.TranslateEnvironmentVariablePath(locationPath); // Check that actual location exists, otherwise directory search will throw directory not found exception - if (!FilesFolders.LocationExists(FilesFolders.ReturnPreviousDirectoryIfIncompleteString(locationPath))) + if (!FilesFolders.ReturnPreviousDirectoryIfIncompleteString(locationPath).LocationExists()) return results.ToList(); var useIndexSearch = UseWindowsIndexForDirectorySearch(locationPath); @@ -134,16 +134,24 @@ namespace Flow.Launcher.Plugin.Explorer.Search token.ThrowIfCancellationRequested(); - // var directoryResult = await TopLevelDirectorySearchBehaviourAsync(WindowsIndexTopLevelFolderSearchAsync, - // DirectoryInfoClassSearch, - // useIndexSearch, - // query, - // locationPath, - // token).ConfigureAwait(false); + IEnumerable directoryResult; + + if (query.Search.Contains('>')) + { + directoryResult = + await Settings.PathEnumerator.EnumerateAsync(locationPath, "", false, token) + .ConfigureAwait(false); + } + else + { + directoryResult = DirectoryInfoSearch.TopLevelDirectorySearch(query, query.Search, token); + } + + token.ThrowIfCancellationRequested(); - // results.UnionWith(directoryResult); + results.UnionWith(directoryResult.Select(searchResult => ResultManager.CreateResult(query, searchResult))); return results.ToList(); } @@ -153,10 +161,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search return actionKeyword == Settings.FileContentSearchActionKeyword; } - private List DirectoryInfoClassSearch(Query query, string querySearch, CancellationToken token) - { - return DirectoryInfoSearch.TopLevelDirectorySearch(query, querySearch, token); - } public async Task> TopLevelDirectorySearchBehaviourAsync( Func>> windowsIndexSearch, diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs deleted file mode 100644 index e42d78f9a..000000000 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex -{ - public interface IIndexProvider - { - public ValueTask> SearchAsync(Query query, CancellationToken token); - public ValueTask> ContentSearchAsync(Query query, CancellationToken token); - } -} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs index 28e9c0e71..7eb9f06f3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs @@ -19,7 +19,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex // Reserved keywords in oleDB private const string ReservedStringPattern = @"^[`\@\#\^,\&\/\\\$\%_;\[\]]+$"; - private static async Task> ExecuteWindowsIndexSearchAsync(string indexQueryString, string connectionString, Query query, CancellationToken token) + private static async Task> ExecuteWindowsIndexSearchAsync(string indexQueryString, string connectionString, CancellationToken token) { var results = new List(); @@ -82,7 +82,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex Func createQueryHelper, Func constructQuery, List exclusionList, - Query query, CancellationToken token) { var regexMatch = Regex.Match(searchString, ReservedStringPattern); @@ -93,40 +92,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex var constructedQuery = constructQuery(searchString); return - await ExecuteWindowsIndexSearchAsync(constructedQuery, createQueryHelper().ConnectionString, query, token); + await ExecuteWindowsIndexSearchAsync(constructedQuery, createQueryHelper().ConnectionString, token); } - private static List RemoveResultsInExclusionList(List results, List exclusionList, CancellationToken token) + private static void RemoveResultsInExclusionList(List results, IReadOnlyList exclusionList, CancellationToken token) { var indexExclusionListCount = exclusionList.Count; if (indexExclusionListCount == 0) - return results; - - var filteredResults = new List(); - - for (var index = 0; index < results.Count; index++) - { - token.ThrowIfCancellationRequested(); - - var excludeResult = false; - - for (var i = 0; i < indexExclusionListCount; i++) - { - token.ThrowIfCancellationRequested(); - - if (results[index].SubTitle.StartsWith(exclusionList[i].Path, StringComparison.OrdinalIgnoreCase)) - { - excludeResult = true; - break; - } - } - - if (!excludeResult) - filteredResults.Add(results[index]); - } - - return filteredResults; + return; + results.RemoveAll(searchResult => + exclusionList.Any(exclude => searchResult.FullPath.StartsWith(exclude.Path, StringComparison.OrdinalIgnoreCase)) + ); } internal static bool PathIsIndexed(string path) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs similarity index 64% rename from Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexManager.cs rename to Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs index 72f5e9cb1..1e64c54f6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs @@ -4,18 +4,18 @@ using System.Threading.Tasks; namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex { - public class WindowsIndexManager : IIndexProvider + public class WindowsIndexSearchManager : IIndexProvider, IContentIndexProvider, IPathEnumerable { private Settings Settings { get; } private QueryConstructor QueryConstructor { get; } - public WindowsIndexManager(Settings settings) + public WindowsIndexSearchManager(Settings settings) { Settings = settings; QueryConstructor = new QueryConstructor(Settings); } - private async Task> WindowsIndexFileContentSearchAsync(Query query, string querySearchString, + private async Task> WindowsIndexFileContentSearchAsync(string querySearchString, CancellationToken token) { if (string.IsNullOrEmpty(querySearchString)) @@ -26,13 +26,12 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex QueryConstructor.CreateQueryHelper, QueryConstructor.QueryForFileContentSearch, Settings.IndexSearchExcludedSubdirectoryPaths, - query, token).ConfigureAwait(false); } - private async Task> WindowsIndexFilesAndFoldersSearchAsync(Query query, string querySearchString, + private async Task> WindowsIndexFilesAndFoldersSearchAsync(string querySearchString, CancellationToken token) { return await WindowsIndex.WindowsIndexSearchAsync( @@ -40,12 +39,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex QueryConstructor.CreateQueryHelper, QueryConstructor.QueryForAllFilesAndFolders, Settings.IndexSearchExcludedSubdirectoryPaths, - query, token).ConfigureAwait(false); } - private async Task> WindowsIndexTopLevelFolderSearchAsync(Query query, string path, + private async Task> WindowsIndexTopLevelFolderSearchAsync(string path,string search, CancellationToken token) { var queryConstructor = new QueryConstructor(Settings); @@ -55,16 +53,21 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex queryConstructor.CreateQueryHelper, queryConstructor.QueryForTopLevelDirectorySearch, Settings.IndexSearchExcludedSubdirectoryPaths, - query, token).ConfigureAwait(false); } - public ValueTask> SearchAsync(Query query, CancellationToken token) + public async ValueTask> SearchAsync(string search, CancellationToken token) { - return default; + return await WindowsIndexFilesAndFoldersSearchAsync(search, token); } - public ValueTask> ContentSearchAsync(Query query, CancellationToken token) + public async ValueTask> ContentSearchAsync(string search, CancellationToken token) { - return default; + return await WindowsIndexFileContentSearchAsync(search, token); + } + public async ValueTask> EnumerateAsync(string path, string search, bool recursive, CancellationToken token) + { + if(recursive) + return await WindowsIndexFilesAndFoldersSearchAsync(search, token).ConfigureAwait(false); + return await WindowsIndexTopLevelFolderSearchAsync(path, search, token); } } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index f3ce8abc5..d9d2a788f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -6,6 +6,7 @@ using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json.Serialization; namespace Flow.Launcher.Plugin.Explorer { @@ -44,18 +45,44 @@ namespace Flow.Launcher.Plugin.Explorer public bool WarnWindowsSearchServiceOff { get; set; } = true; - private List _indexProviders; + private IReadOnlyList _indexProviders; + private IReadOnlyList _fileContentIndexProviders; + private IReadOnlyList _pathEnumerables; public Settings() { + var everythingManager = new EverythingSearchManager(this); + var windowsIndexManager = new WindowsIndexSearchManager(this); + _indexProviders = new List() { - new EverythingSearchManager(this), - new WindowsIndexManager(this) + everythingManager, + windowsIndexManager + }; + + _pathEnumerables = new List() + { + everythingManager, + windowsIndexManager + }; + + _fileContentIndexProviders = new List + { + windowsIndexManager, everythingManager }; } + public IndexSearchEngineOption IndexSearchEngine { get; set; } + [JsonIgnore] public IIndexProvider IndexProvider => _indexProviders[(int)IndexSearchEngine]; + + public PathTraversalEngineOption PathEnumerationEngine { get; set; } + [JsonIgnore] + public IPathEnumerable PathEnumerator => _pathEnumerables[(int)PathEnumerationEngine]; + public ContentIndexSearchEngineOption ContentSearchEngine { get; set; } + [JsonIgnore] + public IContentIndexProvider ContentIndexProvider => _fileContentIndexProviders[(int)ContentSearchEngine]; + public enum PathTraversalEngineOption { Everything, @@ -68,11 +95,17 @@ namespace Flow.Launcher.Plugin.Explorer Everything, WindowsIndex } - #region Everything Settings - + + public enum ContentIndexSearchEngineOption + { + Everything, + WindowsIndex + } public bool LaunchHidden { get; set; } = false; + #region Everything Settings + public string EverythingInstalledPath { get; set; } public SortOption[] SortOptions { get; set; } = Enum.GetValues(); From 9b471de3cf818f4026a20b4e5e7551e24e96f0da Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Sun, 15 May 2022 15:15:56 -0500 Subject: [PATCH 0011/2008] Implement Path Enumeration and ContentSearch --- Flow.Launcher/MainWindow.xaml.cs | 2 +- .../DirectoryInfo/DirectoryInfoSearch.cs | 33 ++++++------ .../Search/Everything/EverythingAPI.cs | 38 ++++++------- .../Everything/EverythingSearchManager.cs | 29 ++++++++-- .../Everything/EverythingSearchOption.cs | 35 ++++++++++++ .../Search/IContentIndexProvider.cs | 2 +- .../Search/SearchManager.cs | 54 +++++++++++++++---- .../WindowsIndex/WindowsIndexSearchManager.cs | 4 +- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 5 +- 9 files changed, 147 insertions(+), 55 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 366407182..37f205288 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -520,7 +520,7 @@ namespace Flow.Launcher && QueryTextBox.CaretIndex == QueryTextBox.Text.Length) { var queryWithoutActionKeyword = - QueryBuilder.Build(QueryTextBox.Text.Trim(), PluginManager.NonGlobalPlugins).Search; + QueryBuilder.Build(QueryTextBox.Text.Trim(), PluginManager.NonGlobalPlugins)?.Search; if (FilesFolders.IsLocationPathString(queryWithoutActionKeyword)) { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs index 14c90d57f..27498002c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs @@ -10,7 +10,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo { public static class DirectoryInfoSearch { - internal static List TopLevelDirectorySearch(Query query, string search, CancellationToken token) + internal static IEnumerable TopLevelDirectorySearch(Query query, string search, CancellationToken token) { var criteria = ConstructSearchCriteria(search); @@ -44,31 +44,36 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo return incompleteName; } - private static List DirectorySearch(EnumerationOptions enumerationOption, Query query, string search, + private static IEnumerable DirectorySearch(EnumerationOptions enumerationOption, Query query, string search, string searchCriteria, CancellationToken token) { - var results = new List(); + var results = new List(); var path = FilesFolders.ReturnPreviousDirectoryIfIncompleteString(search); - var folderList = new List(); - var fileList = new List(); - try { var directoryInfo = new System.IO.DirectoryInfo(path); - foreach (var fileSystemInfo in directoryInfo.EnumerateFileSystemInfos(searchCriteria, enumerationOption) - ) + foreach (var fileSystemInfo in directoryInfo.EnumerateFileSystemInfos(searchCriteria, enumerationOption)) { if (fileSystemInfo is System.IO.DirectoryInfo) { - folderList.Add(ResultManager.CreateFolderResult(fileSystemInfo.Name, fileSystemInfo.FullName, - fileSystemInfo.FullName, query, 0, true, false)); + results.Add(new SearchResult() + { + FullPath = fileSystemInfo.FullName, + Type = ResultType.Folder, + WindowsIndexed = false + }); } else { - fileList.Add(ResultManager.CreateFileResult(fileSystemInfo.FullName, query, 0, true, false)); + results.Add(new SearchResult() + { + FullPath = fileSystemInfo.FullName, + Type = ResultType.File, + WindowsIndexed = false + }); } token.ThrowIfCancellationRequested(); @@ -77,13 +82,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo catch (Exception e) { Log.Exception("Flow.Plugin.Explorer.", nameof(DirectoryInfoSearch), e); - results.Add(new Result {Title = e.Message, Score = 501}); - - return results; + throw; } // Initial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection. - return results.Concat(folderList.OrderBy(x => x.Title)).Concat(fileList.OrderBy(x => x.Title)).ToList(); + return results.OrderBy(r=>r.Type).ThenBy(r=>r.FullPath); } } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 501ce5b22..92538d554 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -107,38 +107,38 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything /// The offset. /// The max count. /// - public static IEnumerable SearchAsync(string keyword, - CancellationToken token, - SortOption sortOption = SortOption.NAME_ASCENDING, - string parentPath = "", - bool recursive = false, - int offset = 0, - int maxCount = 100) + public static IEnumerable SearchAsync(EverythingSearchOption option, + CancellationToken token) { - if (offset < 0) - throw new ArgumentOutOfRangeException(nameof(offset)); + if (option.Offset < 0) + throw new ArgumentOutOfRangeException(nameof(option.Offset), option.Offset, "Offset must be greater than or equal to 0"); - if (maxCount < 0) - throw new ArgumentOutOfRangeException(nameof(maxCount)); + if (option.MaxCount < 0) + throw new ArgumentOutOfRangeException(nameof(option.MaxCount), option.MaxCount, "MaxCount must be greater than or equal to 0"); lock (syncObject) { - if (keyword.StartsWith("@")) + if (option.Keyword.StartsWith("@")) { EverythingApiDllImport.Everything_SetRegex(true); - keyword = keyword[1..]; + option.Keyword = option.Keyword[1..]; } - if (!string.IsNullOrEmpty(parentPath)) + if (!string.IsNullOrEmpty(option.ParentPath)) { - keyword += $" {(recursive ? "" : "parent:")}\"{parentPath}\""; + option.Keyword += $" {(option.IsRecursive ? "" : "parent:")}\"{option.ParentPath}\""; } - EverythingApiDllImport.Everything_SetSearchW(keyword); - EverythingApiDllImport.Everything_SetOffset(offset); - EverythingApiDllImport.Everything_SetMax(maxCount); + if (option.IsContentSearch) + { + option.Keyword += $" content:\"{option.ContentSearchKeyword}\""; + } - EverythingApiDllImport.Everything_SetSort(sortOption); + EverythingApiDllImport.Everything_SetSearchW(option.Keyword); + EverythingApiDllImport.Everything_SetOffset(option.Offset); + EverythingApiDllImport.Everything_SetMax(option.MaxCount); + + EverythingApiDllImport.Everything_SetSort(option.SortOption); if (token.IsCancellationRequested) { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index 14069f678..3bd4a3c7c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -8,7 +8,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IPathEnumerable { private Settings Settings { get; } - + public EverythingSearchManager(Settings settings) { Settings = settings; @@ -17,16 +17,35 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public ValueTask> SearchAsync(string search, CancellationToken token) { - return ValueTask.FromResult(EverythingApi.SearchAsync(search, token, Settings.SortOption)); + return ValueTask.FromResult(EverythingApi.SearchAsync( + new EverythingSearchOption(search, Settings.SortOption), + token)); } - public ValueTask> ContentSearchAsync(string search, CancellationToken token) + public ValueTask> ContentSearchAsync(string plainSearch, + string contentSearch, CancellationToken token) { - return new ValueTask>(new List()); + if (!Settings.EnableEverythingContentSearch) + { + return new ValueTask>(new List()); + } + + return new ValueTask>(EverythingApi.SearchAsync( + new EverythingSearchOption( + plainSearch, + Settings.SortOption, + true, + contentSearch), + token)); } public ValueTask> EnumerateAsync(string path, string search, bool recursive, CancellationToken token) { return new ValueTask>( - EverythingApi.SearchAsync("", token, Settings.SortOption, path, recursive)); + EverythingApi.SearchAsync( + new EverythingSearchOption(search, + Settings.SortOption, + parentPath: path, + isRecursive: recursive), + token)); } } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs new file mode 100644 index 000000000..ef41cf1f0 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs @@ -0,0 +1,35 @@ +using Flow.Launcher.Plugin.Everything.Everything; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + public struct EverythingSearchOption + { + public EverythingSearchOption(string keyword, + SortOption sortOption, + bool isContentSearch = false, + string contentSearchKeyword = "", + string parentPath = "", + bool isRecursive = true, + int offset = 0, + int maxCount = 100) + { + Keyword = keyword; + SortOption = sortOption; + ContentSearchKeyword = contentSearchKeyword; + IsContentSearch = isContentSearch; + ParentPath = parentPath; + IsRecursive = isRecursive; + Offset = offset; + MaxCount = maxCount; + } + public string Keyword { get; set; } + public SortOption SortOption { get; set; } + public string ParentPath { get; set; } + public bool IsRecursive { get; set; } + + public bool IsContentSearch { get; set; } + public string ContentSearchKeyword { get; set; } + public int Offset { get;set; } + public int MaxCount { get; set; } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs index b2142357e..bd7e14a66 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs @@ -6,6 +6,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search { public interface IContentIndexProvider { - public ValueTask> ContentSearchAsync(string search, CancellationToken token); + public ValueTask> ContentSearchAsync(string plainSearch, string contentSearch, CancellationToken token); } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 93707dcf2..99a5c35ba 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -1,4 +1,5 @@ using Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo; +using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; using Flow.Launcher.Plugin.SharedCommands; @@ -59,9 +60,13 @@ namespace Flow.Launcher.Plugin.Explorer.Search IEnumerable searchResults; - if (IsFileContentSearch(query.ActionKeyword)) + if (ActionKeywordMatch(query, Settings.ActionKeyword.FileContentSearchActionKeyword)) { - searchResults = await Settings.ContentIndexProvider.ContentSearchAsync(query.Search, token); + if (Settings.ContentIndexProvider is EverythingSearchManager && !Settings.EnableEverythingContentSearch) + { + return EverythingContentSearchResult(query); + } + searchResults = await Settings.ContentIndexProvider.ContentSearchAsync("", query.Search, token); } else { @@ -74,9 +79,10 @@ namespace Flow.Launcher.Plugin.Explorer.Search results.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false)); } - if ((ActionKeywordMatch(query, Settings.ActionKeyword.IndexSearchActionKeyword) || - ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword)) && - querySearch.Length > 0 && + if (((ActionKeywordMatch(query, Settings.ActionKeyword.IndexSearchActionKeyword) || + ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword)) && + querySearch.Length > 0) || + ActionKeywordMatch(query, Settings.ActionKeyword.FileContentSearchActionKeyword) && !querySearch.IsLocationPathString()) { if (searchResults != null) @@ -101,7 +107,27 @@ namespace Flow.Launcher.Plugin.Explorer.Search Settings.ActionKeyword.IndexSearchActionKeyword => Settings.IndexSearchKeywordEnabled && keyword == Settings.IndexSearchActionKeyword, Settings.ActionKeyword.QuickAccessActionKeyword => Settings.QuickAccessKeywordEnabled && - keyword == Settings.QuickAccessActionKeyword + keyword == Settings.QuickAccessActionKeyword, + _ => throw new ArgumentOutOfRangeException(nameof(allowedActionKeyword), allowedActionKeyword, "actionKeyword out of range") + }; + } + + private static List EverythingContentSearchResult(Query query) + { + return new List() + { + new() + { + Title = "Do you want to enable content search for Everything?", + SubTitle = "It can be super slow without index (which is only supported in Everything 1.5+)", + IcoPath = "Images/search.png", + Action = c => + { + Settings.EnableEverythingContentSearch = true; + Context.API.ChangeQuery(query.RawQuery, true); + return false; + } + } }; } @@ -120,7 +146,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search var isEnvironmentVariablePath = querySearch[1..].Contains("%\\"); var locationPath = querySearch; - + if (isEnvironmentVariablePath) locationPath = EnvironmentVariables.TranslateEnvironmentVariablePath(locationPath); @@ -136,18 +162,24 @@ namespace Flow.Launcher.Plugin.Explorer.Search IEnumerable directoryResult; - if (query.Search.Contains('>')) + var recursiveIndicatorIndex = query.Search.IndexOf('>'); + + if (recursiveIndicatorIndex > 0 && Settings.PathEnumerationEngine != Settings.PathTraversalEngineOption.Direct) { directoryResult = - await Settings.PathEnumerator.EnumerateAsync(locationPath, "", false, token) + await Settings.PathEnumerator.EnumerateAsync(query.Search[..recursiveIndicatorIndex], + query.Search[(recursiveIndicatorIndex + 1)..], + true, + token) .ConfigureAwait(false); + } else { directoryResult = DirectoryInfoSearch.TopLevelDirectorySearch(query, query.Search, token); } - - + + token.ThrowIfCancellationRequested(); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs index 1e64c54f6..05e75c646 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs @@ -59,9 +59,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex { return await WindowsIndexFilesAndFoldersSearchAsync(search, token); } - public async ValueTask> ContentSearchAsync(string search, CancellationToken token) + public async ValueTask> ContentSearchAsync(string plainSearch, string contentSearch, CancellationToken token) { - return await WindowsIndexFileContentSearchAsync(search, token); + return await WindowsIndexFileContentSearchAsync(contentSearch, token); } public async ValueTask> EnumerateAsync(string path, string search, bool recursive, CancellationToken token) { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index d9d2a788f..3c91eeabd 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -67,7 +67,8 @@ namespace Flow.Launcher.Plugin.Explorer _fileContentIndexProviders = new List { - windowsIndexManager, everythingManager + windowsIndexManager, + everythingManager, }; } @@ -111,6 +112,8 @@ namespace Flow.Launcher.Plugin.Explorer public SortOption[] SortOptions { get; set; } = Enum.GetValues(); public SortOption SortOption { get; set; } = SortOption.NAME_ASCENDING; + + public bool EnableEverythingContentSearch { get; set; } = false; #endregion From d5e1b7cb2232ae93c28ffc1e0bd0764912b6aa4c Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 30 Jun 2022 23:56:15 -0500 Subject: [PATCH 0012/2008] Rewrite Explorer View Logic based on MVVM Pattern to avoid complicated View Logic --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 7 + Flow.Launcher/PublicAPIInstance.cs | 2 + .../Flow.Launcher.Plugin.Explorer.csproj | 1 - .../Languages/en.xaml | 1 + Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 2 +- .../Search/QuickAccessLinks/QuickAccess.cs | 4 +- .../Search/WindowsIndex/WindowsIndex.cs | 2 +- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 7 +- .../ViewModels/ActionKeywordModel.cs | 57 +++++ .../ViewModels/RelayCommand.cs | 27 +++ .../ViewModels/SettingsViewModel.cs | 185 +++++++++++++- .../Views/ActionKeywordSetting.xaml | 2 +- .../Views/ActionKeywordSetting.xaml.cs | 55 ++--- .../Views/ExplorerSettings.xaml | 169 +++++++------ .../Views/ExplorerSettings.xaml.cs | 225 +----------------- 15 files changed, 401 insertions(+), 345 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/ActionKeywordModel.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/RelayCommand.cs diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 69057820e..8ec0c6eae 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -181,6 +181,13 @@ namespace Flow.Launcher.Plugin /// The actionkeyword that is supposed to be removed void RemoveActionKeyword(string pluginId, string oldActionKeyword); + /// + /// Check whether specific ActionKeyword is assigned to any of the plugin + /// + /// The actionkeyword for checking + /// True if the actionkeyword is already assigned, False otherwise + bool ActionKeywordAssigned(string actionKeyword); + /// /// Log debug message /// Message will only be logged in Debug mode diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 81f7a2389..7cb704ccc 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -142,6 +142,8 @@ namespace Flow.Launcher public void AddActionKeyword(string pluginId, string newActionKeyword) => PluginManager.AddActionKeyword(pluginId, newActionKeyword); + public bool ActionKeywordAssigned(string actionKeyword) => PluginManager.ActionKeywordRegistered(actionKeyword); + public void RemoveActionKeyword(string pluginId, string oldActionKeyword) => PluginManager.RemoveActionKeyword(pluginId, oldActionKeyword); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj index ae48ac3ee..4d2a4e50a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -50,5 +50,4 @@ - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index e23bd77bd..78c822614 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -20,6 +20,7 @@ Delete Edit Add + General Setting Customise Action Keywords Quick Access Links Index Search Excluded Paths diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index d8879a4f6..5c651266a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -44,7 +44,7 @@ namespace Flow.Launcher.Plugin.Explorer if (Settings.QuickFolderAccessLinks.Any()) { Settings.QuickAccessLinks = Settings.QuickFolderAccessLinks; - Settings.QuickFolderAccessLinks = new List(); + Settings.QuickFolderAccessLinks = new(); } contextMenu = new ContextMenu(Context, Settings, viewModel); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/QuickAccessLinks/QuickAccess.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/QuickAccessLinks/QuickAccess.cs index 55975c2a5..b39e410d6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/QuickAccessLinks/QuickAccess.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/QuickAccessLinks/QuickAccess.cs @@ -8,7 +8,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks { private const int quickAccessResultScore = 100; - internal static List AccessLinkListMatched(Query query, List accessLinks) + internal static List AccessLinkListMatched(Query query, IEnumerable accessLinks) { if (string.IsNullOrEmpty(query.Search)) return new List(); @@ -29,7 +29,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks }).ToList(); } - internal static List AccessLinkListAll(Query query, List accessLinks) + internal static List AccessLinkListAll(Query query, IEnumerable accessLinks) => accessLinks .OrderBy(x => x.Type) .ThenBy(x => x.Name) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs index 7eb9f06f3..64717b41c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs @@ -81,7 +81,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex string searchString, Func createQueryHelper, Func constructQuery, - List exclusionList, + IEnumerable exclusionList, CancellationToken token) { var regexMatch = Regex.Match(searchString, ReservedStringPattern); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 3c91eeabd..af334fdd0 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -5,6 +5,7 @@ using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Text.Json.Serialization; @@ -14,14 +15,14 @@ namespace Flow.Launcher.Plugin.Explorer { public int MaxResult { get; set; } = 100; - public List QuickAccessLinks { get; set; } = new List(); + public ObservableCollection QuickAccessLinks { get; set; } = new (); // as at v1.7.0 this is to maintain backwards compatibility, need to be removed afterwards. - public List QuickFolderAccessLinks { get; set; } = new List(); + public ObservableCollection QuickFolderAccessLinks { get; set; } = new (); public bool UseWindowsIndexForDirectorySearch { get; set; } = true; - public List IndexSearchExcludedSubdirectoryPaths { get; set; } = new List(); + public ObservableCollection IndexSearchExcludedSubdirectoryPaths { get; set; } = new ObservableCollection(); public string SearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/ActionKeywordModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/ActionKeywordModel.cs new file mode 100644 index 000000000..2f614ead8 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/ActionKeywordModel.cs @@ -0,0 +1,57 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace Flow.Launcher.Plugin.Explorer.Views +{ + public class ActionKeywordModel : INotifyPropertyChanged + { + private static Settings _settings; + + public event PropertyChangedEventHandler PropertyChanged; + + public static void Init(Settings settings) + { + _settings = settings; + } + + internal ActionKeywordModel(Settings.ActionKeyword actionKeyword, string description) + { + KeywordProperty = actionKeyword; + Description = description; + } + + public string Description { get; private init; } + + internal Settings.ActionKeyword KeywordProperty { get; } + + private void OnPropertyChanged([CallerMemberName] string propertyName = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + private string? keyword; + + public string Keyword + { + get => keyword ??= _settings.GetActionKeyword(KeywordProperty); + set + { + keyword = value; + _settings.SetActionKeyword(KeywordProperty, value); + OnPropertyChanged(); + } + } + private bool? enabled; + + public bool Enabled + { + get => enabled ??= _settings.GetActionKeywordEnabled(KeywordProperty); + set + { + enabled = value; + _settings.SetActionKeywordEnabled(KeywordProperty, value); + OnPropertyChanged(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/RelayCommand.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/RelayCommand.cs new file mode 100644 index 000000000..ff704b679 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/RelayCommand.cs @@ -0,0 +1,27 @@ +using System; +using System.Windows.Input; + +namespace Flow.Launcher.Plugin.Explorer.ViewModels +{ + internal class RelayCommand : ICommand + { + private Action _action; + + public RelayCommand(Action action) + { + _action = action; + } + + public virtual bool CanExecute(object parameter) + { + return true; + } + + public event EventHandler CanExecuteChanged; + + public virtual void Execute(object parameter) + { + _action?.Invoke(parameter); + } + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index e1793ad47..182acc80a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -2,8 +2,13 @@ using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Plugin.Explorer.Search; using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; +using Flow.Launcher.Plugin.Explorer.Views; +using System.Collections.ObjectModel; using System.Diagnostics; +using System.IO; using System.Threading.Tasks; +using System.Windows.Forms; +using System.Windows.Input; namespace Flow.Launcher.Plugin.Explorer.ViewModels { @@ -25,6 +30,175 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels Context.API.SaveSettingJsonStorage(); } + + public AccessLink SelectedQuickAccessLink { get; set; } + public AccessLink SelectedIndexSearchExcludedPath { get; set; } + public ActionKeywordModel SelectedActionKeyword { get; set; } + + + + public ICommand RemoveLinkCommand => new RelayCommand(RemoveLink); + public ICommand EditLinkCommand => new RelayCommand(EditLink); + public ICommand AddLinkCommand => new RelayCommand(AddLink); + + public ICommand EditActionKeywordCommand => new RelayCommand(EditActionKeyword); + + private void EditActionKeyword(object obj) + { + if (SelectedActionKeyword is not ActionKeywordModel actionKeyword) + { + ShowUnselectedMessage(); + return; + } + + var actionKeywordWindow = new ActionKeywordSetting(actionKeyword, Context.API); + + if (actionKeywordWindow.ShowDialog() ?? false) + { + if (actionKeyword.Enabled && !actionKeywordWindow.KeywordEnabled) + { + Context.API.RemoveActionKeyword(Context.CurrentPluginMetadata.ID, actionKeyword.Keyword); + } + else if (!actionKeyword.Enabled && actionKeywordWindow.KeywordEnabled) + { + Context.API.AddActionKeyword(Context.CurrentPluginMetadata.ID, actionKeyword.Keyword); + } + else if (actionKeyword.Enabled && actionKeywordWindow.KeywordEnabled) + { + // same keyword will have dialog result false + Context.API.RemoveActionKeyword(Context.CurrentPluginMetadata.ID, actionKeyword.Keyword); + Context.API.AddActionKeyword(Context.CurrentPluginMetadata.ID, actionKeywordWindow.ActionKeyword); + } + + (actionKeyword.Keyword, actionKeyword.Enabled) = (actionKeywordWindow.ActionKeyword, actionKeywordWindow.KeywordEnabled); + } + + } + + private AccessLink? PromptUserSelectPath(ResultType type, string initialDirectory = null) + { + AccessLink newAccessLink = null; + + if (type is ResultType.Folder) + { + var folderBrowserDialog = new FolderBrowserDialog(); + + if (initialDirectory is not null) + folderBrowserDialog.InitialDirectory = initialDirectory; + + if (folderBrowserDialog.ShowDialog() != DialogResult.OK) + return newAccessLink; + + newAccessLink = new AccessLink { Path = folderBrowserDialog.SelectedPath }; + } + else if (type is ResultType.File) + { + var openFileDialog = new OpenFileDialog(); + if (initialDirectory is not null) + openFileDialog.InitialDirectory = initialDirectory; + + if (openFileDialog.ShowDialog() != DialogResult.OK) + return newAccessLink; + + newAccessLink = new AccessLink { Path = openFileDialog.FileName }; + } + return newAccessLink; + } + + private void EditLink(object obj) + { + if (obj is not string container) return; + + AccessLink selectedLink; + ObservableCollection collection; + + switch (container) + { + case "QuickAccessLink": + if (SelectedQuickAccessLink == null) + { + ShowUnselectedMessage(); + return; + } + selectedLink = SelectedQuickAccessLink; + collection = Settings.QuickAccessLinks; + break; + case "IndexSearchExcludedPaths": + if (SelectedIndexSearchExcludedPath == null) + { + ShowUnselectedMessage(); + return; + } + selectedLink = SelectedIndexSearchExcludedPath; + collection = Settings.IndexSearchExcludedSubdirectoryPaths; + break; + default: + return; + } + + var link = PromptUserSelectPath(selectedLink.Type, + selectedLink.Type == ResultType.Folder + ? selectedLink.Path + : Path.GetDirectoryName(selectedLink.Path)); + + if (link is null) + return; + + collection.Remove(selectedLink); + collection.Add(link); + } + + private void ShowUnselectedMessage() + { + string warning = Context.API.GetTranslation("plugin_explorer_make_selection_warning"); + MessageBox.Show(warning); + } + + private void AddLink(object obj) + { + if (obj is not string container) return; + + var folderBrowserDialog = new FolderBrowserDialog(); + + if (folderBrowserDialog.ShowDialog() != DialogResult.OK) + return; + + var newAccessLink = new AccessLink { Path = folderBrowserDialog.SelectedPath }; + + + switch (container) + { + case "QuickAccessLink": + if (SelectedQuickAccessLink == null) return; + Settings.QuickAccessLinks.Add(newAccessLink); + break; + case "IndexSearchExcludedPaths": + if (SelectedIndexSearchExcludedPath == null) return; + Settings.IndexSearchExcludedSubdirectoryPaths.Add(newAccessLink); + break; + } + } + + private void RemoveLink(object obj) + { + if (obj is not string container) return; + + switch (container) + { + case "QuickAccessLink": + if (SelectedQuickAccessLink == null) return; + Settings.QuickAccessLinks.Remove(SelectedQuickAccessLink); + break; + case "IndexSearchExcludedPaths": + if (SelectedIndexSearchExcludedPath == null) return; + Settings.IndexSearchExcludedSubdirectoryPaths.Remove(SelectedIndexSearchExcludedPath); + break; + } + Save(); + } + + + internal void RemoveLinkFromQuickAccess(AccessLink selectedRow) => Settings.QuickAccessLinks.Remove(selectedRow); internal void RemoveAccessLinkFromExcludedIndexPaths(AccessLink selectedRow) => Settings.IndexSearchExcludedSubdirectoryPaths.Remove(selectedRow); @@ -41,16 +215,11 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels Process.Start(psi); } - internal void UpdateActionKeyword(Settings.ActionKeyword modifiedActionKeyword, string newActionKeyword, string oldActionKeyword) - { + internal void UpdateActionKeyword(Settings.ActionKeyword modifiedActionKeyword, string newActionKeyword, string oldActionKeyword) => PluginManager.ReplaceActionKeyword(Context.CurrentPluginMetadata.ID, oldActionKeyword, newActionKeyword); - } - internal bool IsActionKeywordAlreadyAssigned(string newActionKeyword) - { - return PluginManager.ActionKeywordRegistered(newActionKeyword); - } + internal bool IsActionKeywordAlreadyAssigned(string newActionKeyword) => PluginManager.ActionKeywordRegistered(newActionKeyword); internal bool IsNewActionKeywordGlobal(string newActionKeyword) => newActionKeyword == Query.GlobalPluginWildcardSign; } -} +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml index a46918483..e36d9b92e 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml @@ -96,7 +96,7 @@ Name="ChkActionKeywordEnabled" Width="auto" VerticalAlignment="Center" - IsChecked="{Binding Enabled}" + IsChecked="{Binding KeywordEnabled}" ToolTip="{DynamicResource plugin_explorer_actionkeyword_enabled_tooltip}" /> diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs index 27e4a0b9a..918adb527 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs @@ -13,9 +13,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views /// public partial class ActionKeywordSetting : Window { - private SettingsViewModel settingsViewModel; - - public ActionKeywordView CurrentActionKeyword { get; set; } + public ActionKeywordModel CurrentActionKeyword { get; set; } public string ActionKeyword { @@ -23,24 +21,22 @@ namespace Flow.Launcher.Plugin.Explorer.Views set { // Set Enable to be true if user change ActionKeyword - Enabled = true; + KeywordEnabled = true; actionKeyword = value; } } - public bool Enabled { get; set; } + public bool KeywordEnabled { get; set; } private string actionKeyword; + private readonly IPublicAPI api; - public ActionKeywordSetting(SettingsViewModel settingsViewModel, - ActionKeywordView selectedActionKeyword) + public ActionKeywordSetting(ActionKeywordModel selectedActionKeyword, IPublicAPI api) { - this.settingsViewModel = settingsViewModel; - CurrentActionKeyword = selectedActionKeyword; - + this.api = api; ActionKeyword = selectedActionKeyword.Keyword; - Enabled = selectedActionKeyword.Enabled; + KeywordEnabled = selectedActionKeyword.Enabled; InitializeComponent(); @@ -52,56 +48,43 @@ namespace Flow.Launcher.Plugin.Explorer.Views if (string.IsNullOrEmpty(ActionKeyword)) ActionKeyword = Query.GlobalPluginWildcardSign; - if (CurrentActionKeyword.Keyword == ActionKeyword && CurrentActionKeyword.Enabled == Enabled) + if (CurrentActionKeyword.Keyword == ActionKeyword && CurrentActionKeyword.Enabled == KeywordEnabled) { + DialogResult = false; Close(); return; } + if (ActionKeyword == "") + { + ActionKeyword = "*"; + } if (ActionKeyword == Query.GlobalPluginWildcardSign) switch (CurrentActionKeyword.KeywordProperty) { case Settings.ActionKeyword.FileContentSearchActionKeyword: - MessageBox.Show(settingsViewModel.Context.API.GetTranslation("plugin_explorer_globalActionKeywordInvalid")); + MessageBox.Show(api.GetTranslation("plugin_explorer_globalActionKeywordInvalid")); return; case Settings.ActionKeyword.QuickAccessActionKeyword: - MessageBox.Show(settingsViewModel.Context.API.GetTranslation("plugin_explorer_quickaccess_globalActionKeywordInvalid")); + MessageBox.Show(api.GetTranslation("plugin_explorer_quickaccess_globalActionKeywordInvalid")); return; } - var oldActionKeyword = CurrentActionKeyword.Keyword; - - if (!Enabled || !settingsViewModel.IsActionKeywordAlreadyAssigned(ActionKeyword)) + if (!KeywordEnabled || !api.ActionKeywordAssigned(ActionKeyword)) { - // Update View Data - CurrentActionKeyword.Keyword = Enabled == true ? ActionKeyword : Query.GlobalPluginWildcardSign; - CurrentActionKeyword.Enabled = Enabled; - - switch (Enabled) - { - // reset to global so it does not take up an action keyword when disabled - // not for null Enable plugin - case false when oldActionKeyword != Query.GlobalPluginWildcardSign: - settingsViewModel.UpdateActionKeyword(CurrentActionKeyword.KeywordProperty, - Query.GlobalPluginWildcardSign, oldActionKeyword); - break; - default: - settingsViewModel.UpdateActionKeyword(CurrentActionKeyword.KeywordProperty, - CurrentActionKeyword.Keyword, oldActionKeyword); - break; - } - + DialogResult = true; Close(); return; } // The keyword is not valid, so show message - MessageBox.Show(settingsViewModel.Context.API.GetTranslation("newActionKeywordsHasBeenAssigned")); + MessageBox.Show(api.GetTranslation("newActionKeywordsHasBeenAssigned")); } private void BtnCancel_OnClick(object sender, RoutedEventArgs e) { + DialogResult = false; Close(); } private void TxtCurrentActionKeyword_OnKeyDown(object sender, KeyEventArgs e) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index a441c10b5..1e14ba09d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -4,13 +4,13 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:qa="clr-namespace:Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks" xmlns:viewModels="clr-namespace:Flow.Launcher.Plugin.Explorer.ViewModels" xmlns:views="clr-namespace:Flow.Launcher.Plugin.Explorer.Views" - xmlns:qa="clr-namespace:Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks" + d:DataContext="{d:DesignInstance viewModels:SettingsViewModel}" d:DesignHeight="450" d:DesignWidth="800" - mc:Ignorable="d" - d:DataContext="{d:DesignInstance viewModels:SettingsViewModel}"> + mc:Ignorable="d"> @@ -37,7 +37,7 @@ + Text="{Binding Keyword}"> - @@ -61,10 +69,10 @@ - + - @@ -74,56 +82,47 @@ - - - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Flow.Launcher/MessageBoxEx.xaml.cs b/Flow.Launcher/MessageBoxEx.xaml.cs new file mode 100644 index 000000000..dccf8131b --- /dev/null +++ b/Flow.Launcher/MessageBoxEx.xaml.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Forms; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using Flow.Launcher.Core.Resource; +using YamlDotNet.Core.Tokens; + +namespace Flow.Launcher +{ + /// + /// MessageBoxEx.xaml에 대한 상호 작용 논리 + /// + public partial class MessageBoxEx : Window + { + static MessageBoxEx msgBox; + static string Button_id; + public MessageBoxEx() + { + InitializeComponent(); + } + + + public static string Show(string txtMessage, string txtTitle) + { + msgBox = new MessageBoxEx(); + msgBox.TitleTextBlock.Text = txtTitle; + msgBox.DescTextBlock.Text = txtMessage; + //msgBox.label1.Text = txtMessage; + //msgBox.Text = txtTitle; + msgBox.ShowDialog(); + return Button_id; + } + + private void BtnCancel_OnClick(object sender, RoutedEventArgs e) + { + DialogResult = false; + Close(); + } + + private void BtnAdd_OnClick(object sender, RoutedEventArgs e) + { + + Close(); + } + + private void cmdEsc_OnPress(object sender, ExecutedRoutedEventArgs e) + { + DialogResult = false; + Close(); + } + } +} diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 950694db5..c246db1af 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -48,10 +48,9 @@ - + - + @@ -2906,7 +2905,12 @@ Margin="0,0,12,0" Click="ClearLogFolder" Content="{Binding CheckLogFolder, UpdateSourceTrigger=PropertyChanged}" /> + - + Margin="5,0,5,0" + Click="Button_Click" + Content="{DynamicResource cancel}" /> + + + diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index 9ceb9789d..70758540d 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -10,7 +10,9 @@ using Flow.Launcher.ViewModel; using ModernWpf; using ModernWpf.Controls; using System; +using System.Diagnostics; using System.IO; +using System.Security.Policy; using System.Windows; using System.Windows.Data; using System.Windows.Forms; diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index 60dc95e2e..0c25dcc85 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -799,6 +799,7 @@ namespace Flow.Launcher.ViewModel #region about public string Website => Constant.Website; + public string SponsorPage => Constant.SponsorPage; public string ReleaseNotes => _updater.GitHubRepository + @"/releases/latest"; public string Documentation => Constant.Documentation; public string Docs => Constant.Docs; From d70c0ce58c601fe0ac70b127eab7c9cf0f77f49d Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 24 Nov 2022 20:24:08 +0900 Subject: [PATCH 0146/2008] Add Become A sponsor button --- Flow.Launcher/SettingWindow.xaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 4a8a52ea1..2c0e4db25 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -2863,7 +2863,6 @@ NavigateUri="{Binding SponsorPage, Mode=OneWay}" RequestNavigate="OnRequestNavigate" TextDecorations="None"> - Date: Thu, 24 Nov 2022 20:05:07 +0800 Subject: [PATCH 0147/2008] Store CultureInfo in i18n manager --- Flow.Launcher.Core/Resource/Internationalization.cs | 7 ++++++- Flow.Launcher/ViewModel/MainViewModel.cs | 10 +--------- Flow.Launcher/ViewModel/SettingWindowViewModel.cs | 4 +--- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index 4568e92f3..91bcfdf5a 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -17,6 +17,7 @@ namespace Flow.Launcher.Core.Resource public class Internationalization { public Settings Settings { get; set; } + public CultureInfo CurrentCulture { get; private set; } private const string Folder = "Languages"; private const string DefaultFile = "en.xaml"; private const string Extension = ".xaml"; @@ -62,6 +63,7 @@ namespace Flow.Launcher.Core.Resource { LoadLanguage(AvailableLanguages.English); _oldResources.Clear(); + CurrentCulture = new CultureInfo("en"); } public void ChangeLanguage(string languageCode) @@ -96,9 +98,12 @@ namespace Flow.Launcher.Core.Resource { LoadLanguage(language); } - Settings.Language = language.LanguageCode; CultureInfo.CurrentCulture = new CultureInfo(language.LanguageCode); CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture; + CurrentCulture = CultureInfo.CurrentCulture; + + // Raise event after this.CurrentCulture is set + Settings.Language = language.LanguageCode; _ = Task.Run(() => { UpdatePluginMetadataTranslations(); diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 109cfc81e..5be065429 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -65,16 +65,10 @@ namespace Flow.Launcher.ViewModel Settings = settings; Settings.PropertyChanged += (_, args) => { - if (args.PropertyName == nameof(Settings.WindowSize)) - { - } switch (args.PropertyName) { case nameof(Settings.WindowSize): OnPropertyChanged(nameof(MainWindowWidth)); break; - case nameof(Settings.Language): - Culture = new CultureInfo(Settings.Language); - break; } }; @@ -106,8 +100,6 @@ namespace Flow.Launcher.ViewModel RegisterClockAndDateUpdateAsync(); SetOpenResultModifiers(); - - Culture = new CultureInfo(Settings.Language); } private void RegisterViewUpdate() @@ -343,7 +335,7 @@ namespace Flow.Launcher.ViewModel public Settings Settings { get; } public string ClockText { get; private set; } public string DateText { get; private set; } - public CultureInfo Culture { get; set; } + public CultureInfo Culture => InternationalizationManager.Instance.CurrentCulture; private async Task RegisterClockAndDateUpdateAsync() { diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index c51e3e421..f31e838fa 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -56,14 +56,12 @@ namespace Flow.Launcher.ViewModel OnPropertyChanged(nameof(ClockText)); break; case nameof(Settings.Language): - Culture = new CultureInfo(Settings.Language); OnPropertyChanged(nameof(ClockText)); OnPropertyChanged(nameof(DateText)); break; } }; - Culture = new CultureInfo(Settings.Language); } public Settings Settings { get; set; } @@ -87,7 +85,7 @@ namespace Flow.Launcher.ViewModel } } - public CultureInfo Culture { get; private set; } + public CultureInfo Culture => InternationalizationManager.Instance.CurrentCulture; public bool StartFlowLauncherOnSystemStartup { From 303d3b97541715af83a2fd02d8209c49cfbffb88 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 24 Nov 2022 14:18:31 -0600 Subject: [PATCH 0148/2008] remove task.run outside --- Flow.Launcher/ViewModel/ResultViewModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index d12a765ae..282c45f46 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -15,7 +15,7 @@ namespace Flow.Launcher.ViewModel public class ResultViewModel : BaseModel { private static PrivateFontCollection fontCollection = new(); - private static Dictionary fonts = new(); + private static Dictionary fonts = new(); public ResultViewModel(Result result, Settings settings) { @@ -173,7 +173,7 @@ namespace Flow.Launcher.ViewModel } // We need to modify the property not field here to trigger the OnPropertyChanged event - var i = await Task.Run(async () => await ImageLoader.LoadAsync(imagePath, loadFullImage)); + var i = await ImageLoader.LoadAsync(imagePath, loadFullImage); Image = i; } From fb3a23fb2c58b040966bf11fcef42377b79e03c6 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 24 Nov 2022 14:19:16 -0600 Subject: [PATCH 0149/2008] remove unnecessary local variable --- Flow.Launcher/ViewModel/ResultViewModel.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 282c45f46..2d61f6cab 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -173,8 +173,7 @@ namespace Flow.Launcher.ViewModel } // We need to modify the property not field here to trigger the OnPropertyChanged event - var i = await ImageLoader.LoadAsync(imagePath, loadFullImage); - Image = i; + Image = await ImageLoader.LoadAsync(imagePath, loadFullImage).ConfigureAwait(false); } public Result Result { get; } From f3fe26bd55f8da09aa8487b8b89ade76c775a20b Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 24 Nov 2022 15:08:54 -0600 Subject: [PATCH 0150/2008] Adjust ComboBox binding --- .../Views/ExplorerSettings.xaml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index 5a3f73b0a..539d65b70 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -161,11 +161,6 @@ - - - - - + SelectedItem="{Binding SelectedIndexSearchEngine}" + DisplayMemberPath="Description"/> + SelectedItem="{Binding SelectedContentSearchEngine}" + DisplayMemberPath="Description"/> From ec810865ccca19557eac5caab3c06043c0dac5ec Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 24 Nov 2022 15:09:02 -0600 Subject: [PATCH 0151/2008] Port Everything string --- .../Languages/en.xaml | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index 8256b82c5..6fdfaf7c1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -1,5 +1,4 @@ - @@ -91,4 +90,32 @@ Remove the current {0} from Quick Access Show Windows Context Menu + + Warning: Everything service is not running + Error while querying Everything + Sort By + Name + Path + Size + Extension + Type Name + Date Created + Date Modified + Attributes + File List FileName + Run Count + Date Recently Changed + Date Accessed + Date Run + + + Warning: This is not a Fast Sort option, searches may be slow + + Everything Installation + Installing Everything service. Please wait... + Successfully installed Everything service + Failed to automatically install Everything service. Please manually install it from https://www.voidtools.com + Click here to start it + Unable to find an Everything installation, would you like to manually select a location?{0}{0}Click no and Everything will be automatically installed for you + \ No newline at end of file From 2da557c2db001419dec497ffe8a074064f7ddd79 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 24 Nov 2022 16:46:20 -0600 Subject: [PATCH 0152/2008] fix path equality check --- .../Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index f814214dd..7bee3747e 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -1,7 +1,6 @@ using Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo; using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; -using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; using Flow.Launcher.Plugin.SharedCommands; using System; using System.Collections.Generic; @@ -31,12 +30,12 @@ namespace Flow.Launcher.Plugin.Explorer.Search public bool Equals(Result x, Result y) { - return x.SubTitle == y.SubTitle; + return x.Title == y.Title && x.SubTitle == y.SubTitle; } public int GetHashCode(Result obj) { - return obj.SubTitle?.GetHashCode() ?? 0; + return HashCode.Combine(obj.Title.GetHashCode(), obj.SubTitle?.GetHashCode() ?? 0); } } From 786e9427d9fe9e27b6b14c3a3939c1142e2040a4 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 24 Nov 2022 17:06:22 -0600 Subject: [PATCH 0153/2008] Apply IndexSearchExcludedPaths to Index Search in a unified way --- Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 7bee3747e..d9beea456 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -99,6 +99,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search results.Add(ResultManager.CreateResult(query, search)); } + results.RemoveWhere(r => Settings.IndexSearchExcludedSubdirectoryPaths.Any( + excludedPath => r.SubTitle.StartsWith(excludedPath.Path, StringComparison.OrdinalIgnoreCase))); + return results.ToList(); } From 17bc59d0bf21780b960fba351db78dba016f6127 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Fri, 25 Nov 2022 13:59:30 +1100 Subject: [PATCH 0154/2008] update sponsor link --- Flow.Launcher.Infrastructure/Constant.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Constant.cs b/Flow.Launcher.Infrastructure/Constant.cs index ed4e34fee..b0eebd2df 100644 --- a/Flow.Launcher.Infrastructure/Constant.cs +++ b/Flow.Launcher.Infrastructure/Constant.cs @@ -45,7 +45,7 @@ namespace Flow.Launcher.Infrastructure public const string Logs = "Logs"; public const string Website = "https://flowlauncher.com"; - public const string SponsorPage = "https://opencollective.com/flow-launcher"; + public const string SponsorPage = "https://github.com/sponsors/Flow-Launcher"; public const string GitHub = "https://github.com/Flow-Launcher/Flow.Launcher"; public const string Docs = "https://flowlauncher.com/docs"; } From 30987f9c95e22bee43f16ccb8b7cb3ce74cbcf38 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 25 Nov 2022 12:00:37 +0800 Subject: [PATCH 0155/2008] Use DefaultThreadCurrentCulture for culture in app domain --- .../Resource/Internationalization.cs | 14 ++++++++------ .../UserSettings/Settings.cs | 1 - .../Converters/QuerySuggestionBoxConverter.cs | 5 +++-- Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- Flow.Launcher/ViewModel/SettingWindowViewModel.cs | 2 +- Plugins/Flow.Launcher.Plugin.Calculator/Main.cs | 6 +++--- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index 91bcfdf5a..acc693ed5 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -17,7 +17,6 @@ namespace Flow.Launcher.Core.Resource public class Internationalization { public Settings Settings { get; set; } - public CultureInfo CurrentCulture { get; private set; } private const string Folder = "Languages"; private const string DefaultFile = "en.xaml"; private const string Extension = ".xaml"; @@ -63,7 +62,6 @@ namespace Flow.Launcher.Core.Resource { LoadLanguage(AvailableLanguages.English); _oldResources.Clear(); - CurrentCulture = new CultureInfo("en"); } public void ChangeLanguage(string languageCode) @@ -98,11 +96,15 @@ namespace Flow.Launcher.Core.Resource { LoadLanguage(language); } - CultureInfo.CurrentCulture = new CultureInfo(language.LanguageCode); + // Culture of this thread + // Use CreateSpecificCulture to preserve possible user-override settings in Windows + CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(language.LanguageCode); CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture; - CurrentCulture = CultureInfo.CurrentCulture; + // App domain + CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture(language.LanguageCode); + CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.DefaultThreadCurrentCulture; - // Raise event after this.CurrentCulture is set + // Raise event after culture is set Settings.Language = language.LanguageCode; _ = Task.Run(() => { @@ -191,7 +193,7 @@ namespace Flow.Launcher.Core.Resource { p.Metadata.Name = pluginI18N.GetTranslatedPluginTitle(); p.Metadata.Description = pluginI18N.GetTranslatedPluginDescription(); - pluginI18N.OnCultureInfoChanged(CultureInfo.CurrentCulture); + pluginI18N.OnCultureInfoChanged(CultureInfo.DefaultThreadCurrentCulture); } catch (Exception e) { diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 33072b53d..3561c6ffe 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -6,7 +6,6 @@ using System.Text.Json.Serialization; using System.Windows; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; -using Flow.Launcher; using Flow.Launcher.ViewModel; namespace Flow.Launcher.Infrastructure.UserSettings diff --git a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs index ecdfc5851..1e39473e0 100644 --- a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs +++ b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs @@ -52,7 +52,8 @@ namespace Flow.Launcher.Converters // Check if Text will be larger then our QueryTextBox System.Windows.Media.Typeface typeface = new Typeface(QueryTextBox.FontFamily, QueryTextBox.FontStyle, QueryTextBox.FontWeight, QueryTextBox.FontStretch); - System.Windows.Media.FormattedText ft = new FormattedText(QueryTextBox.Text, System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, typeface, QueryTextBox.FontSize, Brushes.Black); + // TODO: Obsolete warning? + System.Windows.Media.FormattedText ft = new FormattedText(QueryTextBox.Text, System.Globalization.CultureInfo.DefaultThreadCurrentCulture, System.Windows.FlowDirection.LeftToRight, typeface, QueryTextBox.FontSize, Brushes.Black); var offset = QueryTextBox.Padding.Right; @@ -75,4 +76,4 @@ namespace Flow.Launcher.Converters throw new NotImplementedException(); } } -} \ No newline at end of file +} diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 5be065429..4db8e3df3 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -335,7 +335,7 @@ namespace Flow.Launcher.ViewModel public Settings Settings { get; } public string ClockText { get; private set; } public string DateText { get; private set; } - public CultureInfo Culture => InternationalizationManager.Instance.CurrentCulture; + public CultureInfo Culture => CultureInfo.DefaultThreadCurrentCulture; private async Task RegisterClockAndDateUpdateAsync() { diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index f31e838fa..de4544233 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -85,7 +85,7 @@ namespace Flow.Launcher.ViewModel } } - public CultureInfo Culture => InternationalizationManager.Instance.CurrentCulture; + public CultureInfo Culture => CultureInfo.DefaultThreadCurrentCulture; public bool StartFlowLauncherOnSystemStartup { diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs index bc79219b6..d5dcdacea 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Runtime.InteropServices; @@ -61,7 +61,7 @@ namespace Flow.Launcher.Plugin.Caculator switch (_settings.DecimalSeparator) { case DecimalSeparator.Comma: - case DecimalSeparator.UseSystemLocale when CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator == ",": + case DecimalSeparator.UseSystemLocale when CultureInfo.DefaultThreadCurrentCulture.NumberFormat.NumberDecimalSeparator == ",": expression = query.Search.Replace(",", "."); break; default: @@ -157,7 +157,7 @@ namespace Flow.Launcher.Plugin.Caculator private string GetDecimalSeparator() { - string systemDecimalSeperator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; + string systemDecimalSeperator = CultureInfo.DefaultThreadCurrentCulture.NumberFormat.NumberDecimalSeparator; switch (_settings.DecimalSeparator) { case DecimalSeparator.UseSystemLocale: return systemDecimalSeperator; From e38a3b0505677b78b511ce85169dbaa728262f4a Mon Sep 17 00:00:00 2001 From: DB p Date: Fri, 25 Nov 2022 14:08:37 +0900 Subject: [PATCH 0156/2008] Change Keyword to ws from * --- Plugins/Flow.Launcher.Plugin.WindowsSettings/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/plugin.json b/Plugins/Flow.Launcher.Plugin.WindowsSettings/plugin.json index b5121b36a..17e6eb39b 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/plugin.json @@ -1,6 +1,6 @@ { "ID": "5043CETYU6A748679OPA02D27D99677A", - "ActionKeyword": "*", + "ActionKeyword": "ws", "Description": "Search settings inside Control Panel and Settings App", "Name": "Windows Settings", "Author": "TobiasSekan", From 21babd13dbcca0cf9db31389278aaef0ba4a6279 Mon Sep 17 00:00:00 2001 From: DB p Date: Fri, 25 Nov 2022 15:30:26 +0900 Subject: [PATCH 0157/2008] Fix Plugin Trigger Icon Position --- Flow.Launcher/MainWindow.xaml | 47 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index c71a2d7a3..82c32a3d8 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -260,28 +260,31 @@ Text="{Binding DateText}" Visibility="{Binding Settings.UseDate, Converter={StaticResource BoolToVisibilityConverter}}" /> - - - - - + + + + + + + + From 32e406e575c4e4acce47d4950d2e144865e92b48 Mon Sep 17 00:00:00 2001 From: DB p Date: Fri, 25 Nov 2022 16:20:54 +0900 Subject: [PATCH 0158/2008] Add MinWidth ContextMenu --- Flow.Launcher/MainWindow.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 82c32a3d8..49854ed81 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -210,7 +210,7 @@ - + From 7f375be727f84eab553b8b23718f07c1c037da1f Mon Sep 17 00:00:00 2001 From: DB p Date: Fri, 25 Nov 2022 16:35:00 +0900 Subject: [PATCH 0159/2008] Add SnapPixel --- Flow.Launcher/Themes/Base.xaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Flow.Launcher/Themes/Base.xaml b/Flow.Launcher/Themes/Base.xaml index edb9ce04d..94740a730 100644 --- a/Flow.Launcher/Themes/Base.xaml +++ b/Flow.Launcher/Themes/Base.xaml @@ -87,6 +87,8 @@ + + diff --git a/Flow.Launcher/Themes/BlurBlack Darker.xaml b/Flow.Launcher/Themes/BlurBlack Darker.xaml index 904c7ead4..a8de180d8 100644 --- a/Flow.Launcher/Themes/BlurBlack Darker.xaml +++ b/Flow.Launcher/Themes/BlurBlack Darker.xaml @@ -37,7 +37,6 @@ x:Key="WindowBorderStyle" BasedOn="{StaticResource BaseWindowBorderStyle}" TargetType="{x:Type Border}"> - @@ -48,6 +47,15 @@ + + + + + + + @@ -181,4 +181,22 @@ TargetType="{x:Type TextBlock}"> + + + \ No newline at end of file diff --git a/Flow.Launcher/Themes/Circle Light.xaml b/Flow.Launcher/Themes/Circle Light.xaml index 316023ab3..57e0da832 100644 --- a/Flow.Launcher/Themes/Circle Light.xaml +++ b/Flow.Launcher/Themes/Circle Light.xaml @@ -69,7 +69,7 @@ x:Key="SeparatorStyle" BasedOn="{StaticResource BaseSeparatorStyle}" TargetType="{x:Type Rectangle}"> - + @@ -167,18 +167,18 @@ x:Key="PreviewBorderStyle" BasedOn="{StaticResource BasePreviewBorderStyle}" TargetType="{x:Type Border}"> - + diff --git a/Flow.Launcher/Themes/Circle System.xaml b/Flow.Launcher/Themes/Circle System.xaml index b00f03e76..811b278fa 100644 --- a/Flow.Launcher/Themes/Circle System.xaml +++ b/Flow.Launcher/Themes/Circle System.xaml @@ -70,7 +70,7 @@ x:Key="SeparatorStyle" BasedOn="{StaticResource BaseSeparatorStyle}" TargetType="{x:Type Rectangle}"> - + @@ -164,4 +164,22 @@ TargetType="{x:Type TextBlock}"> + + + \ No newline at end of file diff --git a/Flow.Launcher/Themes/Cyan Dark.xaml b/Flow.Launcher/Themes/Cyan Dark.xaml index c79044f00..77e4b06bc 100644 --- a/Flow.Launcher/Themes/Cyan Dark.xaml +++ b/Flow.Launcher/Themes/Cyan Dark.xaml @@ -164,7 +164,7 @@ 0 0 - 0 0 0 0 + 0 0 0 4 + + + \ No newline at end of file diff --git a/Flow.Launcher/Themes/Darker Glass.xaml b/Flow.Launcher/Themes/Darker Glass.xaml index 1f079de05..d97789b90 100644 --- a/Flow.Launcher/Themes/Darker Glass.xaml +++ b/Flow.Launcher/Themes/Darker Glass.xaml @@ -5,7 +5,7 @@ - + 0 0 0 8 + + diff --git a/Flow.Launcher/Themes/League.xaml b/Flow.Launcher/Themes/League.xaml index f014ed055..7b42b1cd9 100644 --- a/Flow.Launcher/Themes/League.xaml +++ b/Flow.Launcher/Themes/League.xaml @@ -141,9 +141,8 @@ x:Key="PreviewBorderStyle" BasedOn="{StaticResource BasePreviewBorderStyle}" TargetType="{x:Type Border}"> - - - + + diff --git a/Flow.Launcher/Themes/Nord Darker.xaml b/Flow.Launcher/Themes/Nord Darker.xaml index 20f9b16c4..d7641afec 100644 --- a/Flow.Launcher/Themes/Nord Darker.xaml +++ b/Flow.Launcher/Themes/Nord Darker.xaml @@ -3,6 +3,7 @@ + 0 0 0 8 + - + + \ No newline at end of file diff --git a/Flow.Launcher/Themes/Sublime.xaml b/Flow.Launcher/Themes/Sublime.xaml index e03ab7c43..9f46a8077 100644 --- a/Flow.Launcher/Themes/Sublime.xaml +++ b/Flow.Launcher/Themes/Sublime.xaml @@ -5,6 +5,7 @@ + 0 0 0 8 + + + \ No newline at end of file diff --git a/Flow.Launcher/Themes/Win10Light.xaml b/Flow.Launcher/Themes/Win10Light.xaml index c03f6ce1d..28737d14e 100644 --- a/Flow.Launcher/Themes/Win10Light.xaml +++ b/Flow.Launcher/Themes/Win10Light.xaml @@ -5,6 +5,7 @@ + 0 0 0 4 - + diff --git a/Flow.Launcher/Themes/Win11System.xaml b/Flow.Launcher/Themes/Win11System.xaml index 93b761ba2..63d7af073 100644 --- a/Flow.Launcher/Themes/Win11System.xaml +++ b/Flow.Launcher/Themes/Win11System.xaml @@ -6,6 +6,7 @@ + 0 0 0 8 @@ -325,57 +326,57 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + VerticalAlignment="Center"> + + + + + + + diff --git a/Flow.Launcher/Themes/Base.xaml b/Flow.Launcher/Themes/Base.xaml index e28e60e07..e3ad6360e 100644 --- a/Flow.Launcher/Themes/Base.xaml +++ b/Flow.Launcher/Themes/Base.xaml @@ -478,7 +478,8 @@ + - - - + - - - - + + + - @@ -351,14 +338,16 @@ - - - + + + - @@ -367,52 +356,64 @@ - - - + + + - - - - + - + - - - + + + + + - - + diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index fca37a359..1bfaa9c52 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -20,47 +20,51 @@ namespace Flow.Launcher.ViewModel public ResultViewModel(Result result, Settings settings) { - if (result != null) + Settings = settings; + + if (result == null) { - Result = result; + return; + } + Result = result; - if (Result.Glyph is { FontFamily: not null } glyph) + PreviewExtension = Path.GetExtension(result.PreviewImage ?? result.IcoPath); + + if (Result.Glyph is { FontFamily: not null } glyph) + { + // Checks if it's a system installed font, which does not require path to be provided. + if (glyph.FontFamily.EndsWith(".ttf") || glyph.FontFamily.EndsWith(".otf")) { - // Checks if it's a system installed font, which does not require path to be provided. - if (glyph.FontFamily.EndsWith(".ttf") || glyph.FontFamily.EndsWith(".otf")) + string fontFamilyPath = glyph.FontFamily; + + if (!Path.IsPathRooted(fontFamilyPath)) { - string fontFamilyPath = glyph.FontFamily; + fontFamilyPath = Path.Combine(Result.PluginDirectory, fontFamilyPath); + } - if (!Path.IsPathRooted(fontFamilyPath)) + if (fonts.ContainsKey(fontFamilyPath)) + { + Glyph = glyph with { - fontFamilyPath = Path.Combine(Result.PluginDirectory, fontFamilyPath); - } - - if (fonts.ContainsKey(fontFamilyPath)) - { - Glyph = glyph with - { - FontFamily = fonts[fontFamilyPath] - }; - } - else - { - fontCollection.AddFontFile(fontFamilyPath); - fonts[fontFamilyPath] = $"{Path.GetDirectoryName(fontFamilyPath)}/#{fontCollection.Families[^1].Name}"; - Glyph = glyph with - { - FontFamily = fonts[fontFamilyPath] - }; - } + FontFamily = fonts[fontFamilyPath] + }; } else { - Glyph = glyph; + fontCollection.AddFontFile(fontFamilyPath); + fonts[fontFamilyPath] = $"{Path.GetDirectoryName(fontFamilyPath)}/#{fontCollection.Families[^1].Name}"; + Glyph = glyph with + { + FontFamily = fonts[fontFamilyPath] + }; } } + else + { + Glyph = glyph; + } } - Settings = settings; } private Settings Settings { get; } @@ -165,6 +169,13 @@ namespace Flow.Launcher.ViewModel private set => previewImage = value; } + public string PreviewExtension { get; set; } + + public bool PreviewIsImageOrVideo => PreviewExtension is ".jpg" + or ".png" + or ".gif" + or ".mp4"; + public GlyphInfo Glyph { get; set; } private async Task LoadImageAsync() From c622edab99bcffc901de1cd55fdf8610c514d49e Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 26 Nov 2022 06:12:23 +0900 Subject: [PATCH 0172/2008] Add FileType / Ignore Case Senstive --- Flow.Launcher/ViewModel/ResultViewModel.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 1bfaa9c52..20ea9cf7c 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -29,6 +29,11 @@ namespace Flow.Launcher.ViewModel Result = result; PreviewExtension = Path.GetExtension(result.PreviewImage ?? result.IcoPath); + if (PreviewExtension != null) + { + PreviewExtension = PreviewExtension.ToLowerInvariant(); + + } if (Result.Glyph is { FontFamily: not null } glyph) { @@ -173,7 +178,11 @@ namespace Flow.Launcher.ViewModel public bool PreviewIsImageOrVideo => PreviewExtension is ".jpg" or ".png" + or ".avi" + or ".mkv" + or ".bmp" or ".gif" + or ".wmv" or ".mp4"; public GlyphInfo Glyph { get; set; } From c95c276ac7efa66970b03ceea5c8fbd3ef39193c Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 26 Nov 2022 11:43:35 +0800 Subject: [PATCH 0173/2008] fix typo --- Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml index 6d9f916e1..654322805 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml @@ -39,7 +39,7 @@ Please select a program source Are you sure you want to delete the selected program sources? - Another program source with the same location alreaday exists. + Another program source with the same location already exists. Program Source Edit directory and status of this program source. From 2641fa2ce1c2fe1fcc553cc2c7fd1ffc5fab244f Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 26 Nov 2022 11:46:39 +0800 Subject: [PATCH 0174/2008] update wording --- Flow.Launcher/Languages/en.xaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 9074b5df9..a5edd7ee1 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -36,8 +36,7 @@ Hide Flow Launcher when focus is lost Do not show new version notifications Search Window Position - Remember last launch location - Remember Last Location + Remember Last Position Mouse Focused Screen - Center Mouse Focused Screen - Center Top Mouse Focused Screen - Left Top From 21eb6c77915ce8bc9c27fc505f9fe13e4a54610f Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 26 Nov 2022 12:02:17 +0800 Subject: [PATCH 0175/2008] Match text and illustration --- Flow.Launcher/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 54c82974e..01a3904d2 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -246,7 +246,7 @@ Custom Query Hotkey - Enter a custom hotkey to open Flow Laucher and input the specified query automatically. + Press a custom hotkey to open Flow Laucher and input the specified query automatically. Preview Hotkey is unavailable, please select a new hotkey Invalid plugin hotkey From ff63f6f6d7b8bbbdf66210c3bab7b352ce16d23e Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 26 Nov 2022 12:08:21 +0800 Subject: [PATCH 0176/2008] Fix typo --- Flow.Launcher/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 01a3904d2..4af48132f 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -146,7 +146,7 @@ Show result selection hotkey with results. Custom Query Hotkey Custom Query Shortcut - Built-in Shortcuts + Built-in Shortcut Query Shortcut Expansion From 1f8eea76a44108cd46c0eb50f23970f6d24c5f52 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 26 Nov 2022 14:58:07 +0900 Subject: [PATCH 0177/2008] Fix Aligns --- Flow.Launcher/CustomQueryHotkeySetting.xaml | 5 +++-- Flow.Launcher/CustomShortcutSetting.xaml | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml b/Flow.Launcher/CustomQueryHotkeySetting.xaml index 2ac367206..1113cb24d 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml @@ -76,13 +76,13 @@ TextAlignment="Left" TextWrapping="WrapWithOverflow" /> - + @@ -135,6 +135,7 @@ LastChildFill="True"> + diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml.cs index 0ac219962..816029182 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml.cs @@ -1,10 +1,8 @@ using Flow.Launcher.Plugin.BrowserBookmark.Models; -using Microsoft.Win32; -using System; using System.Windows; -using System.Windows.Controls; using System.Windows.Input; using System.Windows.Forms; +using System.Threading.Tasks; namespace Flow.Launcher.Plugin.BrowserBookmark.Views { @@ -25,20 +23,19 @@ namespace Flow.Launcher.Plugin.BrowserBookmark.Views BrowserType = browser.BrowserType, }; } - - private void ConfirmCancelEditCustomBrowser(object sender, RoutedEventArgs e) + + private void ConfirmEditCustomBrowser(object sender, RoutedEventArgs e) { - if (DataContext is CustomBrowser editBrowser && e.Source is System.Windows.Controls.Button button) - { - if (button.Name == "btnConfirm") - { - currentCustomBrowser.Name = editBrowser.Name; - currentCustomBrowser.DataDirectoryPath = editBrowser.DataDirectoryPath; - currentCustomBrowser.BrowserType = editBrowser.BrowserType; - Close(); - } - } + CustomBrowser editBrowser = (CustomBrowser)DataContext; + currentCustomBrowser.Name = editBrowser.Name; + currentCustomBrowser.DataDirectoryPath = editBrowser.DataDirectoryPath; + currentCustomBrowser.BrowserType = editBrowser.BrowserType; + _ = Task.Run(() => Main.ReloadAllBookmarks()); + Close(); + } + private void CancelEditCustomBrowser(object sender, RoutedEventArgs e) + { Close(); } @@ -46,7 +43,7 @@ namespace Flow.Launcher.Plugin.BrowserBookmark.Views { if (e.Key == Key.Enter) { - ConfirmCancelEditCustomBrowser(sender, e); + ConfirmEditCustomBrowser(sender, e); } } @@ -54,8 +51,8 @@ namespace Flow.Launcher.Plugin.BrowserBookmark.Views { var dialog = new FolderBrowserDialog(); dialog.ShowDialog(); - PathTextBox.Text = dialog.SelectedPath; - string folder = dialog.SelectedPath; + CustomBrowser editBrowser = (CustomBrowser)DataContext; + editBrowser.DataDirectoryPath = dialog.SelectedPath; } } } From 2677c6eb0841d62b41f2d5f3247642a1bd94098b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Feb 2023 22:37:32 +0000 Subject: [PATCH 0622/2008] Bump vedantmgoyal2009/winget-releaser from 1 to 2 Bumps [vedantmgoyal2009/winget-releaser](https://github.com/vedantmgoyal2009/winget-releaser) from 1 to 2. - [Release notes](https://github.com/vedantmgoyal2009/winget-releaser/releases) - [Commits](https://github.com/vedantmgoyal2009/winget-releaser/compare/v1...v2) --- updated-dependencies: - dependency-name: vedantmgoyal2009/winget-releaser dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/winget.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/winget.yml b/.github/workflows/winget.yml index fe1b5a5fc..b1d289091 100644 --- a/.github/workflows/winget.yml +++ b/.github/workflows/winget.yml @@ -9,7 +9,7 @@ jobs: # Action can only be run on windows runs-on: windows-latest steps: - - uses: vedantmgoyal2009/winget-releaser@v1 + - uses: vedantmgoyal2009/winget-releaser@v2 with: identifier: Flow-Launcher.Flow-Launcher token: ${{ secrets.WINGET_TOKEN }} From 39c4a2be2ea4bf55e2e2b8aa42058e4b8709e434 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Tue, 14 Feb 2023 16:35:06 +0800 Subject: [PATCH 0623/2008] Auto reload bookmarks when editing checkboxes --- .../Views/CustomBrowserSetting.xaml.cs | 3 +- .../Views/SettingsControl.xaml | 6 +- .../Views/SettingsControl.xaml.cs | 57 ++++++++++++++++--- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml.cs index 816029182..bdef5bf0f 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml.cs @@ -2,7 +2,6 @@ using System.Windows; using System.Windows.Input; using System.Windows.Forms; -using System.Threading.Tasks; namespace Flow.Launcher.Plugin.BrowserBookmark.Views { @@ -30,7 +29,7 @@ namespace Flow.Launcher.Plugin.BrowserBookmark.Views currentCustomBrowser.Name = editBrowser.Name; currentCustomBrowser.DataDirectoryPath = editBrowser.DataDirectoryPath; currentCustomBrowser.BrowserType = editBrowser.BrowserType; - _ = Task.Run(() => Main.ReloadAllBookmarks()); + DialogResult = true; Close(); } diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml index 408256f45..014deff03 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml @@ -18,15 +18,15 @@ + IsChecked="{Binding LoadChromeBookmark}" /> + IsChecked="{Binding LoadEdgeBookmark}" /> + IsChecked="{Binding LoadFirefoxBookmark}" /> - \ No newline at end of file + diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs index 3da66caeb..f08a80147 100644 --- a/Flow.Launcher/HotkeyControl.xaml.cs +++ b/Flow.Launcher/HotkeyControl.xaml.cs @@ -1,4 +1,6 @@ using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; @@ -9,14 +11,37 @@ using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Plugin; using System.Threading; +using NHotkey; namespace Flow.Launcher { - public partial class HotkeyControl : UserControl + public partial class HotkeyControl : UserControl, IDisposable, INotifyPropertyChanged { + public static readonly DependencyProperty HotkeyProperty = DependencyProperty.Register( + nameof(Hotkey), + typeof(string), + typeof(HotkeyControl), + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault) + ); public HotkeyModel CurrentHotkey { get; private set; } public bool CurrentHotkeyAvailable { get; private set; } + public string Hotkey + { + get => (string)GetValue(HotkeyProperty); + set + { + SetValue(HotkeyProperty, value); + OnPropertyChanged(nameof(KeysToDisplay)); + } + } + + public string[] KeysToDisplay => Hotkey.Split(" + "); + + #nullable enable + public EventHandler? Action { get; set; } + #nullable restore + public event EventHandler HotkeyChanged; /// @@ -29,6 +54,28 @@ namespace Flow.Launcher public HotkeyControl() { InitializeComponent(); + Loaded += HotkeyControl_Loaded; + } + + private void HotkeyControl_LostFocus(object o, RoutedEventArgs routedEventArgs) + { + HotKeyMapper.SetHotkey(CurrentHotkey, Action); + } + + private void HotkeyControl_GotFocus(object o, RoutedEventArgs routedEventArgs) + { + HotKeyMapper.RemoveHotkey(Hotkey); + } + + private void HotkeyControl_Loaded(object sender, RoutedEventArgs e) + { + _ = SetHotkeyAsync(Hotkey, false); + + if (Action is not null) + { + GotFocus += HotkeyControl_GotFocus; + LostFocus += HotkeyControl_LostFocus; + } } private CancellationTokenSource hotkeyUpdateSource; @@ -68,8 +115,8 @@ namespace Flow.Launcher public async Task SetHotkeyAsync(HotkeyModel keyModel, bool triggerValidate = true) { - tbHotkey.Text = keyModel.ToString(); - tbHotkey.Select(tbHotkey.Text.Length, 0); + // tbHotkey.Text = keyModel.ToString(); + // tbHotkey.Select(tbHotkey.Text.Length, 0); if (triggerValidate) { @@ -86,6 +133,7 @@ namespace Flow.Launcher if (CurrentHotkeyAvailable) { CurrentHotkey = keyModel; + Hotkey = keyModel.ToString(); // To trigger LostFocus FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), null); Keyboard.ClearFocus(); @@ -94,9 +142,10 @@ namespace Flow.Launcher else { CurrentHotkey = keyModel; + Hotkey = keyModel.ToString(); } } - + public Task SetHotkeyAsync(string keyStr, bool triggerValidate = true) { return SetHotkeyAsync(new HotkeyModel(keyStr), triggerValidate); @@ -104,12 +153,12 @@ namespace Flow.Launcher private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey); - public new bool IsFocused => tbHotkey.IsFocused; + // public new bool IsFocused => tbHotkey.IsFocused; private void tbHotkey_LostFocus(object sender, RoutedEventArgs e) { - tbHotkey.Text = CurrentHotkey?.ToString() ?? ""; - tbHotkey.Select(tbHotkey.Text.Length, 0); + // tbHotkey.Text = CurrentHotkey?.ToString() ?? ""; + // tbHotkey.Select(tbHotkey.Text.Length, 0); } private void tbHotkey_GotFocus(object sender, RoutedEventArgs e) @@ -137,5 +186,25 @@ namespace Flow.Launcher } tbMsg.Visibility = Visibility.Visible; } + + public void Dispose() + { + hotkeyUpdateSource?.Dispose(); + Loaded -= HotkeyControl_Loaded; + GotFocus -= HotkeyControl_GotFocus; + LostFocus -= HotkeyControl_LostFocus; + } + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + private void OnButtonClicked(object sender, RoutedEventArgs e) + { + // TODO + } } } diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 96f80f0c5..e1b42e3d3 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -693,7 +693,7 @@ - @@ -720,7 +720,7 @@ - + @@ -2657,9 +2657,8 @@ Margin="0,0,0,0" HorizontalAlignment="Right" HorizontalContentAlignment="Right" - GotFocus="OnHotkeyControlFocused" - Loaded="OnHotkeyControlLoaded" - LostFocus="OnHotkeyControlFocusLost" /> + Hotkey="{Binding Settings.Hotkey}" + Action="OnToggleHotkey" />  @@ -2684,8 +2683,7 @@ Margin="0,0,0,0" HorizontalAlignment="Right" HorizontalContentAlignment="Right" - Loaded="OnPreviewHotkeyControlLoaded" - LostFocus="OnPreviewHotkeyControlFocusLost" + Hotkey="{Binding Settings.PreviewHotkey}" ValidateKeyGesture="True" />  diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index 7301be130..e7e9273bb 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -17,6 +17,7 @@ using System.Windows.Forms; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Navigation; +using NHotkey; using Button = System.Windows.Controls.Button; using Control = System.Windows.Controls.Control; using KeyEventArgs = System.Windows.Input.KeyEventArgs; @@ -110,41 +111,9 @@ namespace Flow.Launcher #region Hotkey - private void OnHotkeyControlLoaded(object sender, RoutedEventArgs e) + private void OnToggleHotkey(object sender, HotkeyEventArgs e) { - _ = HotkeyControl.SetHotkeyAsync(viewModel.Settings.Hotkey, false); - } - - private void OnHotkeyControlFocused(object sender, RoutedEventArgs e) - { - HotKeyMapper.RemoveHotkey(settings.Hotkey); - } - - private void OnHotkeyControlFocusLost(object sender, RoutedEventArgs e) - { - if (HotkeyControl.CurrentHotkeyAvailable) - { - HotKeyMapper.SetHotkey(HotkeyControl.CurrentHotkey, HotKeyMapper.OnToggleHotkey); - HotKeyMapper.RemoveHotkey(settings.Hotkey); - settings.Hotkey = HotkeyControl.CurrentHotkey.ToString(); - } - else - { - HotKeyMapper.SetHotkey(new HotkeyModel(settings.Hotkey), HotKeyMapper.OnToggleHotkey); - } - } - - private void OnPreviewHotkeyControlLoaded(object sender, RoutedEventArgs e) - { - _ = PreviewHotkeyControl.SetHotkeyAsync(settings.PreviewHotkey, false); - } - - private void OnPreviewHotkeyControlFocusLost(object sender, RoutedEventArgs e) - { - if (PreviewHotkeyControl.CurrentHotkeyAvailable) - { - settings.PreviewHotkey = PreviewHotkeyControl.CurrentHotkey.ToString(); - } + HotKeyMapper.OnToggleHotkey(sender, e); } private void OnDeleteCustomHotkeyClick(object sender, RoutedEventArgs e) From a0b9d7155844aaf3c5c15a4d8cc95d55bb7af919 Mon Sep 17 00:00:00 2001 From: DB p Date: Fri, 12 Apr 2024 20:56:27 +0900 Subject: [PATCH 1160/2008] Sizes and Margins Adjust --- Flow.Launcher/HotkeyControl.xaml | 13 ++++++++----- Flow.Launcher/SettingWindow.xaml | 30 ++++++++++-------------------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/Flow.Launcher/HotkeyControl.xaml b/Flow.Launcher/HotkeyControl.xaml index bea652d56..2dc051205 100644 --- a/Flow.Launcher/HotkeyControl.xaml +++ b/Flow.Launcher/HotkeyControl.xaml @@ -5,7 +5,6 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - d:DesignHeight="45" d:DesignWidth="300" mc:Ignorable="d"> @@ -39,11 +38,16 @@ - + + + + - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 2339941008f40344479c0ac318c223575c633a0f Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 13 Apr 2024 18:13:25 +0900 Subject: [PATCH 1174/2008] Fix Rec Button --- Flow.Launcher/HotkeyControl.xaml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/Flow.Launcher/HotkeyControl.xaml b/Flow.Launcher/HotkeyControl.xaml index cf0fff2ee..1a347ab13 100644 --- a/Flow.Launcher/HotkeyControl.xaml +++ b/Flow.Launcher/HotkeyControl.xaml @@ -79,7 +79,7 @@ + + diff --git a/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs b/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs new file mode 100644 index 000000000..d83b44fac --- /dev/null +++ b/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Flow.Launcher.Resources.Controls +{ + public partial class HotkeyDisplay : UserControl + { + public HotkeyDisplay() + { + InitializeComponent(); + } + + public string Keys + { + get { return (string)GetValue(KeysValueProperty); } + set { SetValue(KeysValueProperty, value); } + } + public static readonly DependencyProperty KeysValueProperty = + DependencyProperty.Register("Keys", typeof(string), typeof(HotkeyDisplay), new PropertyMetadata(string.Empty)); + } +} diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 3e4f827a6..064e86382 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -2722,7 +2722,9 @@ Title="{DynamicResource flowlauncherHotkey}" Icon="" Sub="{DynamicResource flowlauncherHotkeyToolTip}" - Type="Inside" /> + Type="Inside"> + + Date: Thu, 18 Apr 2024 00:32:10 +0900 Subject: [PATCH 1200/2008] Added Hotkey Display Control --- .../Resources/Controls/HotkeyDisplay.xaml | 61 ++++++++++++++++++- .../Resources/Controls/HotkeyDisplay.xaml.cs | 25 +++++++- Flow.Launcher/SettingWindow.xaml | 4 +- 3 files changed, 85 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml b/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml index 269f095f3..d4483393d 100644 --- a/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml @@ -9,7 +9,62 @@ d:DesignWidth="800" mc:Ignorable="d"> - + + + + + + + + diff --git a/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs b/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs index d83b44fac..3549647aa 100644 --- a/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs +++ b/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs @@ -1,5 +1,8 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; using System.Globalization; using System.Linq; using System.Text; @@ -13,6 +16,9 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; +using Windows.Media.Capture.Frames; +using static System.Windows.Forms.LinkLabel; +using static ABI.System.Collections.Generic.IReadOnlyDictionary_Delegates; namespace Flow.Launcher.Resources.Controls { @@ -21,6 +27,9 @@ namespace Flow.Launcher.Resources.Controls public HotkeyDisplay() { InitializeComponent(); + //List stringList =e.NewValue.Split('+').ToList(); + KeysControl.ItemsSource = Values; + } public string Keys @@ -29,6 +38,20 @@ namespace Flow.Launcher.Resources.Controls set { SetValue(KeysValueProperty, value); } } public static readonly DependencyProperty KeysValueProperty = - DependencyProperty.Register("Keys", typeof(string), typeof(HotkeyDisplay), new PropertyMetadata(string.Empty)); + DependencyProperty.Register("Keys", typeof(string), typeof(HotkeyDisplay), new PropertyMetadata(string.Empty, valueChanged)); + + private static void valueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as UserControl; + if (null == control) return; // This should not be possible + + var newValue = e.NewValue as string; + if (null == newValue) return; + + //String[] Values = newValue.Split('+'); + //Debug.WriteLine(Values[0]); + } + + public ObservableCollection Values { get; set; } } } diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 064e86382..1beafd26b 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -2729,7 +2729,9 @@ Title="{DynamicResource flowlauncherHotkey}" Icon="" Sub="{DynamicResource flowlauncherHotkeyToolTip}" - Type="Inside" /> + Type="Inside"> + + From 66125fce2c041472c667f9b2a400dd670aa4231f Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Wed, 17 Apr 2024 10:45:09 -0500 Subject: [PATCH 1201/2008] Split Key to display --- .../Resources/Controls/HotkeyDisplay.xaml.cs | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs b/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs index 3549647aa..7ffd90d5f 100644 --- a/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs +++ b/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml.cs @@ -28,8 +28,8 @@ namespace Flow.Launcher.Resources.Controls { InitializeComponent(); //List stringList =e.NewValue.Split('+').ToList(); + Values = new ObservableCollection(); KeysControl.ItemsSource = Values; - } public string Keys @@ -37,10 +37,13 @@ namespace Flow.Launcher.Resources.Controls get { return (string)GetValue(KeysValueProperty); } set { SetValue(KeysValueProperty, value); } } - public static readonly DependencyProperty KeysValueProperty = - DependencyProperty.Register("Keys", typeof(string), typeof(HotkeyDisplay), new PropertyMetadata(string.Empty, valueChanged)); - private static void valueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + public static readonly DependencyProperty KeysValueProperty = + DependencyProperty.Register("Keys", typeof(string), typeof(HotkeyDisplay), + new PropertyMetadata(string.Empty, keyChanged)); + + + private static void keyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as UserControl; if (null == control) return; // This should not be possible @@ -48,8 +51,14 @@ namespace Flow.Launcher.Resources.Controls var newValue = e.NewValue as string; if (null == newValue) return; - //String[] Values = newValue.Split('+'); - //Debug.WriteLine(Values[0]); + if (d is not HotkeyDisplay hotkeyDisplay) + return; + + hotkeyDisplay.Values.Clear(); + foreach (var key in newValue.Split('+')) + { + hotkeyDisplay.Values.Add(key); + } } public ObservableCollection Values { get; set; } From c6b62f9917ddaf1fa3adba0978372b8e62b4eb62 Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 18 Apr 2024 00:48:29 +0900 Subject: [PATCH 1202/2008] Fix HotkeyDisplay xaml --- .../Resources/Controls/HotkeyDisplay.xaml | 59 +------------------ 1 file changed, 2 insertions(+), 57 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml b/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml index d4483393d..778c77fe5 100644 --- a/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/HotkeyDisplay.xaml @@ -9,62 +9,7 @@ d:DesignWidth="800" mc:Ignorable="d"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + From 5c3d3c7fbfb2fa5f34fcd711b247e21705a8c240 Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 18 Apr 2024 01:00:31 +0900 Subject: [PATCH 1203/2008] Custom Hotkeys to Expander --- Flow.Launcher/SettingWindow.xaml | 241 ++++++++++++++++--------------- 1 file changed, 122 insertions(+), 119 deletions(-) diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 1beafd26b..1f60e326d 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -2751,128 +2751,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs index 01584ee27..546b252df 100644 --- a/Flow.Launcher/HotkeyControl.xaml.cs +++ b/Flow.Launcher/HotkeyControl.xaml.cs @@ -1,30 +1,38 @@ -using System; +#nullable enable + using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Linq; -using System.Runtime.CompilerServices; +using System.Threading.Tasks; using System.Windows; -using System.Windows.Controls; using System.Windows.Input; -using System.Windows.Media; using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure.Hotkey; -using Flow.Launcher.Plugin; -using JetBrains.Annotations; - -#nullable enable namespace Flow.Launcher { - public partial class HotkeyControl : INotifyPropertyChanged + public partial class HotkeyControl { + public string WindowTitle { + get { return (string)GetValue(WindowTitleProperty); } + set { SetValue(WindowTitleProperty, value); } + } + + public static readonly DependencyProperty WindowTitleProperty = DependencyProperty.Register( + nameof(WindowTitle), + typeof(string), + typeof(HotkeyControl), + new PropertyMetadata(string.Empty) + ); + /// /// Designed for Preview Hotkey and KeyGesture. /// public static readonly DependencyProperty ValidateKeyGestureProperty = DependencyProperty.Register( - nameof(ValidateKeyGesture), typeof(bool), typeof(HotkeyControl), - new PropertyMetadata(default(bool))); + nameof(ValidateKeyGesture), + typeof(bool), + typeof(HotkeyControl), + new PropertyMetadata(default(bool)) + ); public bool ValidateKeyGesture { @@ -33,7 +41,11 @@ namespace Flow.Launcher } public static readonly DependencyProperty DefaultHotkeyProperty = DependencyProperty.Register( - nameof(DefaultHotkey), typeof(string), typeof(HotkeyControl), new PropertyMetadata(default(string))); + nameof(DefaultHotkey), + typeof(string), + typeof(HotkeyControl), + new PropertyMetadata(default(string)) + ); public string DefaultHotkey { @@ -54,7 +66,11 @@ namespace Flow.Launcher public static readonly DependencyProperty ChangeHotkeyProperty = DependencyProperty.Register( - nameof(ChangeHotkey), typeof(ICommand), typeof(HotkeyControl), new PropertyMetadata(default(ICommand))); + nameof(ChangeHotkey), + typeof(ICommand), + typeof(HotkeyControl), + new PropertyMetadata(default(ICommand)) + ); public ICommand? ChangeHotkey { @@ -64,8 +80,11 @@ namespace Flow.Launcher public static readonly DependencyProperty HotkeyProperty = DependencyProperty.Register( - nameof(Hotkey), typeof(string), typeof(HotkeyControl), - new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnHotkeyChanged)); + nameof(Hotkey), + typeof(string), + typeof(HotkeyControl), + new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnHotkeyChanged) + ); public string Hotkey { @@ -81,148 +100,50 @@ namespace Flow.Launcher SetKeysToDisplay(CurrentHotkey); } - /*------------------ New Logic Structure Part------------------------*/ - - private void OnPreviewKeyDown(object sender, KeyEventArgs e) - { - if (HotkeyBtn.IsChecked != true) - return; - e.Handled = true; - - //when alt is pressed, the real key should be e.SystemKey - Key key = e.Key == Key.System ? e.SystemKey : e.Key; - - SpecialKeyState specialKeyState = GlobalHotkey.CheckModifiers(); - - var hotkeyModel = new HotkeyModel( - specialKeyState.AltPressed, - specialKeyState.ShiftPressed, - specialKeyState.WinPressed, - specialKeyState.CtrlPressed, - key); - - CurrentHotkey = hotkeyModel; - SetKeysToDisplay(CurrentHotkey); - } - - - // public new bool IsFocused => tbHotkey.IsFocused; - - private void tbHotkey_LostFocus(object sender, RoutedEventArgs e) - { - // tbHotkey.Text = CurrentHotkey?.ToString() ?? ""; - // tbHotkey.Select(tbHotkey.Text.Length, 0); - } - - private void tbHotkey_GotFocus(object sender, RoutedEventArgs e) - { - ResetMessage(); - } - - private void ResetMessage() - { - tbMsg.Text = InternationalizationManager.Instance.GetTranslation("flowlauncherPressHotkey"); - tbMsg.SetResourceReference(TextBox.ForegroundProperty, "Color05B"); - } - - public event PropertyChangedEventHandler? PropertyChanged; - - protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey); - public string? Message { get; set; } - public bool MessageVisibility { get; set; } - public SolidColorBrush? MessageColor { get; set; } + public string EmptyHotkey => InternationalizationManager.Instance.GetTranslation("none"); - - public bool CurrentHotkeyAvailable { get; private set; } - - - private void SetMessage(string messageKey, bool error) - { - Message = InternationalizationManager.Instance.GetTranslation(messageKey); - MessageColor = error ? new SolidColorBrush(Colors.Green) : new SolidColorBrush(Colors.Red); - MessageVisibility = true; - } - - - private string EmptyHotkeyKey = "none"; - public string EmptyHotkey => InternationalizationManager.Instance.GetTranslation(EmptyHotkeyKey); - private const string KeySeparator = " + "; - - public ObservableCollection KeysToDisplay { get; set; } = new ObservableCollection(); - - public bool IsEmpty => KeysToDisplay.Count == 0 || (KeysToDisplay.Count == 1 && KeysToDisplay[0] == EmptyHotkey); + public ObservableCollection KeysToDisplay { get; set; } = new(); public HotkeyModel CurrentHotkey { get; private set; } = new(false, false, false, false, Key.None); - public void StartRecording() + public void GetNewHotkey(object sender, RoutedEventArgs e) { - if (!HotkeyBtn.IsChecked ?? false) - { - return; - } + OpenHotkeyDialog(); + } + private async Task OpenHotkeyDialog() + { if (!string.IsNullOrEmpty(Hotkey)) { HotKeyMapper.RemoveHotkey(Hotkey); } - /* 1. Key Recording Start */ - /* 2. Key Display area clear - * 3. Key Display when typing*/ - } - private void StopRecording() - { - try + var dialog = new HotkeyControlDialog(Hotkey, DefaultHotkey, WindowTitle); + await dialog.ShowAsync(); + switch (dialog.ResultType) { - var converter = new KeyGestureConverter(); - _ = (KeyGesture)converter.ConvertFromString(CurrentHotkey.ToString())!; + case HotkeyControlDialog.EResultType.Cancel: + SetHotkey(Hotkey); + return; + case HotkeyControlDialog.EResultType.Save: + SetHotkey(dialog.ResultValue); + break; + case HotkeyControlDialog.EResultType.Delete: + Delete(); + break; } - catch (Exception e) when (e is NotSupportedException or InvalidEnumArgumentException) - { - SetMessage("Hotkey Invalid", true); - CurrentHotkey = new HotkeyModel(Hotkey); - SetKeysToDisplay(CurrentHotkey); - return; - } - - HotkeyBtn.IsChecked = false; - - SetHotkey(CurrentHotkey, true); - } - - private void ResetToDefault() - { - if (!string.IsNullOrEmpty(Hotkey)) - HotKeyMapper.RemoveHotkey(Hotkey); - Hotkey = DefaultHotkey; - CurrentHotkey = new HotkeyModel(Hotkey); - - SetKeysToDisplay(CurrentHotkey); - - SetHotkey(CurrentHotkey); - - HotkeyBtn.IsChecked = false; } private void SetHotkey(HotkeyModel keyModel, bool triggerValidate = true) { - // tbHotkey.Text = keyModel.ToString(); - // tbHotkey.Select(tbHotkey.Text.Length, 0); - if (triggerValidate) { bool hotkeyAvailable = CheckHotkeyAvailability(keyModel, ValidateKeyGesture); - SetMessage(hotkeyAvailable ? "success" : "hotkeyUnavailable", !hotkeyAvailable); if (!hotkeyAvailable) { @@ -246,7 +167,6 @@ namespace Flow.Launcher HotKeyMapper.RemoveHotkey(Hotkey); Hotkey = ""; SetKeysToDisplay(new HotkeyModel(false, false, false, false, Key.None)); - HotkeyBtn.IsChecked = false; } private void SetKeysToDisplay(HotkeyModel? hotkey) @@ -269,14 +189,5 @@ namespace Flow.Launcher { SetHotkey(new HotkeyModel(keyStr), triggerValidate); } - - - private void HotkeyBtn_OnChecked(object sender, RoutedEventArgs e) => StartRecording(); - - - private void ResetButton_OnClick(object sender, RoutedEventArgs e) => ResetToDefault(); - private void DeleteBtn_OnClick(object sender, RoutedEventArgs e) => Delete(); - - private void StopRecordingBtn_Click(object sender, RoutedEventArgs e) => StopRecording(); } } diff --git a/Flow.Launcher/HotkeyControl2.xaml b/Flow.Launcher/HotkeyControl2.xaml deleted file mode 100644 index 730c9604b..000000000 --- a/Flow.Launcher/HotkeyControl2.xaml +++ /dev/null @@ -1,77 +0,0 @@ - - - diff --git a/Flow.Launcher/HotkeyControl2.xaml.cs b/Flow.Launcher/HotkeyControl2.xaml.cs deleted file mode 100644 index 86973a754..000000000 --- a/Flow.Launcher/HotkeyControl2.xaml.cs +++ /dev/null @@ -1,193 +0,0 @@ -#nullable enable - -using System.Collections.ObjectModel; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Input; -using Flow.Launcher.Core.Resource; -using Flow.Launcher.Helper; -using Flow.Launcher.Infrastructure.Hotkey; - -namespace Flow.Launcher -{ - public partial class HotkeyControl2 - { - public string WindowTitle { - get { return (string)GetValue(WindowTitleProperty); } - set { SetValue(WindowTitleProperty, value); } - } - - public static readonly DependencyProperty WindowTitleProperty = DependencyProperty.Register( - nameof(WindowTitle), - typeof(string), - typeof(HotkeyControl2), - new PropertyMetadata(string.Empty) - ); - - /// - /// Designed for Preview Hotkey and KeyGesture. - /// - public static readonly DependencyProperty ValidateKeyGestureProperty = DependencyProperty.Register( - nameof(ValidateKeyGesture), - typeof(bool), - typeof(HotkeyControl2), - new PropertyMetadata(default(bool)) - ); - - public bool ValidateKeyGesture - { - get { return (bool)GetValue(ValidateKeyGestureProperty); } - set { SetValue(ValidateKeyGestureProperty, value); } - } - - public static readonly DependencyProperty DefaultHotkeyProperty = DependencyProperty.Register( - nameof(DefaultHotkey), - typeof(string), - typeof(HotkeyControl2), - new PropertyMetadata(default(string)) - ); - - public string DefaultHotkey - { - get { return (string)GetValue(DefaultHotkeyProperty); } - set { SetValue(DefaultHotkeyProperty, value); } - } - - private static void OnHotkeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not HotkeyControl2 hotkeyControl) - { - return; - } - - hotkeyControl.SetKeysToDisplay(new HotkeyModel(hotkeyControl.Hotkey)); - hotkeyControl.CurrentHotkey = new HotkeyModel(hotkeyControl.Hotkey); - } - - - public static readonly DependencyProperty ChangeHotkeyProperty = DependencyProperty.Register( - nameof(ChangeHotkey), - typeof(ICommand), - typeof(HotkeyControl2), - new PropertyMetadata(default(ICommand)) - ); - - public ICommand? ChangeHotkey - { - get { return (ICommand)GetValue(ChangeHotkeyProperty); } - set { SetValue(ChangeHotkeyProperty, value); } - } - - - public static readonly DependencyProperty HotkeyProperty = DependencyProperty.Register( - nameof(Hotkey), - typeof(string), - typeof(HotkeyControl2), - new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnHotkeyChanged) - ); - - public string Hotkey - { - get { return (string)GetValue(HotkeyProperty); } - set { SetValue(HotkeyProperty, value); } - } - - public HotkeyControl2() - { - InitializeComponent(); - - HotkeyList.ItemsSource = KeysToDisplay; - SetKeysToDisplay(CurrentHotkey); - } - - private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => - hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey); - - public string EmptyHotkey => InternationalizationManager.Instance.GetTranslation("none"); - - public ObservableCollection KeysToDisplay { get; set; } = new(); - - public HotkeyModel CurrentHotkey { get; private set; } = new(false, false, false, false, Key.None); - - - public void GetNewHotkey(object sender, RoutedEventArgs e) - { - OpenHotkeyDialog(); - } - - private async Task OpenHotkeyDialog() - { - if (!string.IsNullOrEmpty(Hotkey)) - { - HotKeyMapper.RemoveHotkey(Hotkey); - } - - var dialog = new HotkeyControl2Dialog(Hotkey, DefaultHotkey, WindowTitle); - await dialog.ShowAsync(); - switch (dialog.ResultType) - { - case HotkeyControl2Dialog.EResultType.Cancel: - SetHotkey(Hotkey); - return; - case HotkeyControl2Dialog.EResultType.Save: - SetHotkey(dialog.ResultValue); - break; - case HotkeyControl2Dialog.EResultType.Delete: - Delete(); - break; - } - } - - - private void SetHotkey(HotkeyModel keyModel, bool triggerValidate = true) - { - if (triggerValidate) - { - bool hotkeyAvailable = CheckHotkeyAvailability(keyModel, ValidateKeyGesture); - - if (!hotkeyAvailable) - { - return; - } - - Hotkey = keyModel.ToString(); - SetKeysToDisplay(CurrentHotkey); - ChangeHotkey?.Execute(keyModel); - } - else - { - Hotkey = keyModel.ToString(); - ChangeHotkey?.Execute(keyModel); - } - } - - public void Delete() - { - if (!string.IsNullOrEmpty(Hotkey)) - HotKeyMapper.RemoveHotkey(Hotkey); - Hotkey = ""; - SetKeysToDisplay(new HotkeyModel(false, false, false, false, Key.None)); - } - - private void SetKeysToDisplay(HotkeyModel? hotkey) - { - KeysToDisplay.Clear(); - - if (hotkey == null || hotkey == default(HotkeyModel)) - { - KeysToDisplay.Add(EmptyHotkey); - return; - } - - foreach (var key in hotkey.Value.EnumerateDisplayKeys()!) - { - KeysToDisplay.Add(key); - } - } - - public void SetHotkey(string? keyStr, bool triggerValidate = true) - { - SetHotkey(new HotkeyModel(keyStr), triggerValidate); - } - } -} diff --git a/Flow.Launcher/HotkeyControl2Dialog.xaml b/Flow.Launcher/HotkeyControlDialog.xaml similarity index 99% rename from Flow.Launcher/HotkeyControl2Dialog.xaml rename to Flow.Launcher/HotkeyControlDialog.xaml index 2eb62c419..6912a1999 100644 --- a/Flow.Launcher/HotkeyControl2Dialog.xaml +++ b/Flow.Launcher/HotkeyControlDialog.xaml @@ -1,5 +1,5 @@  InternationalizationManager.Instance.GetTranslation("none"); - public HotkeyControl2Dialog(string hotkey, string defaultHotkey, string windowTitle = "") + public HotkeyControlDialog(string hotkey, string defaultHotkey, string windowTitle = "") { WindowTitle = windowTitle switch { diff --git a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml index 84615c155..b60b8e47e 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml +++ b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml @@ -110,7 +110,7 @@ FontSize="14" FontWeight="SemiBold" Text="{DynamicResource flowlauncherHotkey}" /> - - - - @@ -2771,7 +2771,7 @@ Title="{DynamicResource SettingWindowHotkey}" Icon="" Type="Inside"> - @@ -2793,7 +2793,7 @@ Title="{DynamicResource SelectNextPageHotkey}" Icon="" Type="Inside"> - @@ -2802,7 +2802,7 @@ Title="{DynamicResource SelectPrevPageHotkey}" Icon="" Type="Inside"> - @@ -2836,7 +2836,7 @@ Icon="" Sub="{DynamicResource autoCompleteHotkeyToolTip}"> - @@ -2845,7 +2845,7 @@ Title="{DynamicResource autoCompleteHotkey}" Sub="{DynamicResource AdditionalHotkeyToolTip}" Type="InsideFit"> - @@ -2858,7 +2858,7 @@ Margin="0,4,0,0" Icon=""> - @@ -2867,7 +2867,7 @@ Title="{DynamicResource SelectNextItemHotkey}" Sub="{DynamicResource AdditionalHotkeyToolTip}" Type="InsideFit"> - @@ -2879,7 +2879,7 @@ Margin="0,4,0,0" Icon=""> - @@ -2888,7 +2888,7 @@ Title="{DynamicResource SelectPrevItemHotkey}" Sub="{DynamicResource AdditionalHotkeyToolTip}" Type="InsideFit"> - From 806e1246126a242908f43e406290f60a88775ddb Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 23 Apr 2024 12:40:23 +0900 Subject: [PATCH 1245/2008] - Fix Static Hotkey's Uppercases - Adjust Warning Style in dialog - Adjust Warning Text --- Flow.Launcher/HotkeyControlDialog.xaml | 42 +++++++++++--------------- Flow.Launcher/Languages/en.xaml | 2 +- Flow.Launcher/SettingWindow.xaml | 18 +++++------ 3 files changed, 28 insertions(+), 34 deletions(-) diff --git a/Flow.Launcher/HotkeyControlDialog.xaml b/Flow.Launcher/HotkeyControlDialog.xaml index 6912a1999..322f82366 100644 --- a/Flow.Launcher/HotkeyControlDialog.xaml +++ b/Flow.Launcher/HotkeyControlDialog.xaml @@ -24,9 +24,7 @@ - + @@ -38,9 +36,7 @@ FontWeight="SemiBold" Text="{Binding WindowTitle}" TextAlignment="Left" /> - + - + - - - - - - + + + + diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index c92f227b3..6205c06bc 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -310,7 +310,7 @@ Invalid plugin hotkey Update Binding Hotkey - It's unavailable hotkey. + This hotkey is unavailable. Press the keys you want to use for this function. diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 15db60573..89a454fc0 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -2731,13 +2731,13 @@ Title="{DynamicResource OpenContainFolderHotkey}" Icon="" Type="Inside"> - + - + - + - + - + - - + + - - + + From 5a45c5a012d1c0f6832337cf307167dd9c6a93f0 Mon Sep 17 00:00:00 2001 From: Kevin Zhang <45326534+taooceros@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:39:25 -0500 Subject: [PATCH 1246/2008] Use Shell Execute for Shell Plugin RunCommand it would not behavior like win+r without this. try `shell:startup` --- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index f3c34d41d..b3b02cb6d 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -264,6 +264,7 @@ namespace Flow.Launcher.Plugin.Shell var arguments = parts[1]; info.FileName = filename; info.ArgumentList.Add(arguments); + info.UseShellExecute = true; } else { From 7fbea552c8dfd749a19eb8428f685700f68d4f64 Mon Sep 17 00:00:00 2001 From: DB p Date: Wed, 24 Apr 2024 04:10:52 +0900 Subject: [PATCH 1247/2008] Add Vietnamese Support --- .github/actions/spelling/expect.txt | 1 + .../Resource/AvailableLanguages.cs | 7 +- Flow.Launcher/Languages/vi-vn.xaml | 383 ++++++++++++++++++ 3 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 Flow.Launcher/Languages/vi-vn.xaml diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index c4b1ee849..59566af64 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -97,6 +97,7 @@ Português Português (Brasil) Italiano Slovenský +Tiếng Việt Droplex Preinstalled errormetadatafile diff --git a/Flow.Launcher.Core/Resource/AvailableLanguages.cs b/Flow.Launcher.Core/Resource/AvailableLanguages.cs index b6d394d11..46c1ecb54 100644 --- a/Flow.Launcher.Core/Resource/AvailableLanguages.cs +++ b/Flow.Launcher.Core/Resource/AvailableLanguages.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace Flow.Launcher.Core.Resource { @@ -27,6 +27,8 @@ namespace Flow.Launcher.Core.Resource public static Language Turkish = new Language("tr", "Türkçe"); public static Language Czech = new Language("cs", "čeština"); public static Language Arabic = new Language("ar", "اللغة العربية"); + public static Language Vietnamese = new Language("vi-vn", "Tiếng Việt"); + public static List GetAvailableLanguages() { @@ -54,7 +56,8 @@ namespace Flow.Launcher.Core.Resource Slovak, Turkish, Czech, - Arabic + Arabic, + Vietnamese }; return languages; } diff --git a/Flow.Launcher/Languages/vi-vn.xaml b/Flow.Launcher/Languages/vi-vn.xaml new file mode 100644 index 000000000..a54c17df4 --- /dev/null +++ b/Flow.Launcher/Languages/vi-vn.xaml @@ -0,0 +1,383 @@ + + + + Không thể đăng ký phím nóng "{0}". Phím nóng có thể được sử dụng bởi một chương trình khác. Chuyển sang phím nóng khác hoặc thoát khỏi chương trình khác. + Trình khởi chạy luồng + Không thể khởi động {0} + Định dạng tệp plugin Flow Launcher không chính xác + Đặt ở vị trí hàng đầu trong truy vấn này + Hủy trên cùng trong truy vấn này + Thực thi truy vấn:{0} + Thời gian thực hiện lần cuối:{0} + Mở + Cài đặt + Über + Thoát + Đóng + Sao chép + Di chuyển + Dán + Hoàn tác + Chọn tất cả + Ngày tháng + Thư Mục + Văn bản + Chế độ trò chơi + Tạm dừng sử dụng phím nóng. + Đặt lại vị trí + Đặt lại vị trí của cửa sổ tìm kiếm + + + Cài đặt + Tổng quan + Chế độ Portabler + Lưu trữ tất cả cài đặt và dữ liệu người dùng trong một thư mục (hữu ích khi sử dụng với thiết bị lưu trữ di động hoặc dịch vụ đám mây). + Khởi động Flow Launcher khi khởi động hệ thống + Không lưu được tính năng tự khởi động khi khởi động hệ thống + Ẩn Flow Launcher khi mất tiêu điểm + Không hiển thị thông báo khi có phiên bản mới + Vị trí Suchfenster + Ghi nhớ vị trí cuối cùng + Màn hình bằng con trỏ chuột + Màn hình có cửa sổ được tập trung + Màn hình chính + Màn hình tùy chỉnh + Tìm kiếm vị trí cửa sổ trên màn hình + Trung tâm + Trung tâm trên cùng + Liên kết oben + Trên cùng bên phải + Vị trí tùy chỉnh + Sprache + Chọn kiểu truy vấn + Hiển thị/ẩn các kết quả trước đó khi Flow Launcher được kích hoạt lại. + Giữ lại truy vấn cuối cùng + Chọn truy vấn cuối cùng + Trống truy vấn cuối cùng + Số kết quả tối đa + Có thể thiết lập nhanh chóng bằng CTRL+Plus và CTRL+Minus. + Bỏ qua phím nóng khi cửa sổ ở chế độ toàn màn hình + Tắt Flow Launcher khi ứng dụng toàn màn hình đang hoạt động (Được khuyến nghị để chơi trò chơi). + Trình quản lý ngày tháng tiêu chuẩn + Chọn trình quản lý tệp để sử dụng khi mở thư mục. + Trình duyệt chuẩn + Cài đặt cho tab mới, cửa sổ mới và chế độ riêng tư. + Python-Pfad + Node.js-Pfad + Vui lòng chọn chương trình Node.js + Vui lòng chọn pythonw.exe + Luôn bắt đầu nhập ở chế độ tiếng Anh + Tạm thời chuyển phương thức nhập sang tiếng Anh khi kích hoạt Flow. + Cập nhật tự động + Chọn + Ẩn Trình khởi chạy luồng khi khởi động + Ẩn biểu tượng thanh trạng thái + Khi biểu tượng bị ẩn khỏi khay, bạn có thể mở menu Cài đặt bằng cách nhấp chuột phải vào cửa sổ tìm kiếm. + Độ chính xác của tìm kiếm truy vấn + Kết quả tìm kiếm bắt buộc. + Hoạt động bính âm + Cho phép bạn sử dụng Bính âm để tìm kiếm. Bính âm là hệ thống ký hiệu La Mã tiêu chuẩn để dịch văn bản tiếng Trung. + Luôn xem trước + Luôn mở bảng xem trước khi Flow kích hoạt. Nhấn {0} để chuyển đổi chế độ xem trước. + Hiệu ứng đổ bóng không được phép nếu chủ đề hiện tại bật hiệu ứng làm mờ + + + Plugin tìm kiếm + Ctrl+F để tìm kiếm plugin + Không tìm thấy kết quả nào + Vui lòng thử tìm kiếm khác. + Tiện ích mở rộng + Tiện ích mở rộng + Tìm kiếm thêm plugin + Bật + Tắt + Cài đặt từ hành động + Từ khóa hành động + Từ hành động hiện tại + Từ hành động mới + Thay đổi từ hành động + Ưu tiên hiện tại + Ưu tiên mới + Ưu tiên + Thay đổi mức độ ưu tiên của kết quả plugin + Trình cắm + tác giả + Khởi tạo ban đầu: + Abfragezeit: + Phiên bản + Trang web + Gỡ cài đặt + + + + Tải tiện ích mở rộng + Bản phát hành mới + Cập nhật gần đây + Tiện ích mở rộng + Đã cài đặt + Làm mới + Cài đặt + Gỡ cài đặt + Cập nhật + Plugin đã được cài đặt + Phiên bản mới + Plugin này đã được cập nhật trong vòng 7 ngày qua + Đã có bản cập nhật mới + + + + + Giao Diện + Giao diện + Tìm kiếm thêm chủ đề + Cách tạo chủ đề + Xin chào! + Explorer + Tìm kiếm tệp, thư mục và nội dung tệp + Tìm kiếm trên web + Tìm kiếm trên web với sự hỗ trợ của công cụ tìm kiếm khác + Chương trình + Khởi chạy chương trình với tư cách quản trị viên hoặc người dùng khác + ProcessKiller + Chấm dứt các tiến trình không mong muốn + Phông chữ hộp truy vấn + Phông chữ kết quả + chế độ cửa sổ + độ mờ + Chủ đề {0} không tồn tại nên mẫu mặc định được kích hoạt + Tải chủ đề {0} không thành công, mẫu mặc định được kích hoạt + Mở thư mục chủ đề + Mở thư mục chủ đề + Bảng màu + Mặc định hệ thống + Sáng + Tối + Hiệu ứng âm thanh + Phát âm thanh khi cửa sổ tìm kiếm mở + Âm lượng hiệu ứng âm thanh + Điều chỉnh âm lượng của hiệu ứng âm thanh + Hoạt hình + Sử dụng hình động trong giao diện + Tốc độ hoạt ảnh + Tốc độ của hoạt ảnh giao diện người dùng + Chậm + Trung bình + Nhanh + Tùy chỉnh + Giờ + Ngày + + + Phím tắt + Phím tắt + Phím nóng của Flow Launcher + Nhập phím tắt để hiển thị/ẩn Flow Launcher. + Xem trước phím nóng + Nhập phím tắt để hiển thị/ẩn bản xem trước trong cửa sổ tìm kiếm. + Mở công cụ sửa đổi kết quả + Chọn phím bổ trợ để mở kết quả đã chọn từ bàn phím. + Giải thích phím nóng + Hiển thị phím tắt chọn kết quả cùng với kết quả. + Phím tắt truy vấn tùy chỉnh + Lối tắt truy vấn tùy chỉnh + Phím tắt tích hợp + Truy vấn + Phím tắt + Mở rộng + Mô tả + Xóa + Chỉnh sửa + Thêm + Vui lòng chọn một mục + Bạn có chắc chắn muốn xóa tổ hợp phím plugin {0} không? + Bạn có chắc chắn muốn xóa lối tắt: {0} với phần mở rộng {1} không? + Nhận văn bản từ bảng nhớ tạm. + Nhận đường dẫn từ trình thám hiểm đang hoạt động. + Hiệu ứng đổ bóng trong cửa sổ truy vấn + Hiệu ứng đổ bóng gây rất nhiều áp lực lên GPU. Không nên dùng nếu hiệu suất máy tính của bạn bị hạn chế. + Chiều rộng kích thước cửa sổ + Bạn cũng có thể nhanh chóng điều chỉnh điều này bằng cách sử dụng Ctrl+[ và Ctrl+]. + Sử dụng biểu tượng Segoe + Sử dụng Biểu tượng Segoe Fluent cho kết quả truy vấn nếu được hỗ trợ + Nhấn phím + + + Proxy HTTP + Proxy HTTP hoạt động + Máy chủ HTTP + Cổng + Tài Khoản + Mật khẩu + Proxy thử nghiệm + Lưu + Máy chủ không được để trống + Cổng máy chủ không được để trống + Định dạng cổng Falsches + Proxy đã được lưu thành công + Proxy này được chấp nhận + Kết nối với proxy không thành công + + + Giới thiệu + Trang web + GitHub + Tài liệu + Phiên bản + Biểu tượng + Bạn đã kích hoạt Flow Launcher {0} lần + Kiểm tra các bản cập nhật + Trở thành nhà tài trợ + Đã tồn tại một phiên bản mới ({0}). Vui lòng khởi động lại Flow Launcher. + Kiểm tra cập nhật không thành công. Vui lòng kiểm tra kết nối và cài đặt proxy của bạn tới api.github.com. + + Tải xuống bản cập nhật không thành công. Vui lòng kiểm tra cài đặt kết nối và proxy của bạn tới github-cloud.s3.amazonaws.com, + hoặc truy cập https://github.com/Flow-Launcher/Flow.Launcher/releases để tải xuống các bản cập nhật theo cách thủ công. + + Ghi chú phát hành + Mẹo sử dụng + Công cụ dành cho nhà phát triển + cài đặt thư mục + Thư mục nhật ký + Xóa tệp nhật ký + Bạn có chắc chắn muốn xóa tất cả nhật ký không? + Wizard + + + Chọn trình quản lý tệp + Vui lòng chỉ định vị trí tệp của trình quản lý tệp mà bạn đang sử dụng và thêm đối số nếu cần. Đối số mặc định là "%d" và một đường dẫn được nhập tại vị trí đó. Ví dụ: Nếu một lệnh được yêu cầu như "totalcmd.exe /A c:\windows", đối số là /A "%d". + "%f" là một đối số đại diện cho đường dẫn tệp. Nó được sử dụng để nhấn mạnh tên tệp/thư mục khi mở một vị trí tệp cụ thể trong trình quản lý tệp của bên thứ 3. Đối số này chỉ có sẵn trong phần "Arg for File" mục. Nếu trình quản lý tệp không có chức năng đó, bạn có thể sử dụng "%d". + Trình quản lý ngày tháng + Tên hồ sơ + Đường dẫn quản lý tệp + Đối số cho thư mục + Đối số cho tệp + + + Trình duyệt web tiêu chuẩn + Mặc định sử dụng mặc định trình duyệt của hệ điều hành. Nếu được chỉ định, Flow sẽ sử dụng trình duyệt này. + Trình duyệt + Tên trình duyệt + Đường dẫn trình duyệt + Cửa sổ mới + Thẻ Mới + Chế độ riêng tư + + + Thay đổi mức độ ưu tiên + Số càng cao thì kết quả được xếp hạng càng cao. Hãy thử số 5. ​​Nếu bạn muốn kết quả sâu hơn so với các plugin khác, hãy sử dụng số âm + Vui lòng chỉ định số nguyên hợp lệ cho mức độ ưu tiên! + + + Từ khóa hành động cũ + Từ khóa hành động mới + Viết tắt + Fertig + Không thể tìm thấy plugin được chỉ định + Từ khóa hành động mới không được để trống + Từ khóa hành động đã được một plugin khác sử dụng. Vui lòng đặt từ khóa hành động khác. + Thành công + Đã hoàn tất thành công + Sử dụng * nếu bạn muốn xác định từ khóa hành động. + + + Phím nóng truy vấn tùy chỉnh + Nhấn phím nóng tùy chỉnh để mở Flow Launcher và tự động nhập truy vấn được chỉ định. + Xem trước + Tổ hợp phím không khả dụng, vui lòng chọn tổ hợp phím khác + Tổ hợp phím plugin không hợp lệ + Cập nhật + + + Phím tắt truy vấn tùy chỉnh + Nhập một phím tắt tự động mở rộng theo truy vấn đã chỉ định. + Một phím tắt được mở rộng khi nó khớp chính xác với truy vấn. + +Nếu bạn thêm tiền tố '@' trong khi nhập phím tắt, phím tắt đó sẽ khớp với bất kỳ vị trí nào trong truy vấn. Các phím tắt dựng sẵn khớp với bất kỳ vị trí nào trong truy vấn. + + Phím tắt đã tồn tại, vui lòng nhập Phím tắt mới hoặc chỉnh sửa phím tắt hiện có. + Phím tắt và/hoặc phần mở rộng của nó trống. + + + Tổ hợp phím không khả dụng + + + Phiên bản + Thời gian + Vui lòng cho chúng tôi biết ứng dụng bị lỗi như thế nào để chúng tôi có thể khắc phục lỗi. + Gửi báo cáo + Huỷ bỏ + Chung + Ngoại lệ + Loại ngoại lệ + Nguồn + Ngăn xếp dấu vết + Gửi + Đã gửi báo cáo thành công + Báo cáo lỗi + Trình khởi chạy luồng có lỗi + + + Cảnh báo nhỏ... + + + Kiểm tra cập nhật mới + Bạn đã có phiên bản mới nhất + Tìm thấy cập nhật + Đang cập nhật... + + Flow Launcher không thể di chuyển dữ liệu hồ sơ của bạn sang phiên bản cập nhật mới. + Vui lòng di chuyển thủ công thư mục dữ liệu hồ sơ của bạn từ {0} sang {1} + + Cập nhật mới + Đã có sẵn V{0} của Flow Launcher + Đã xảy ra lỗi khi cài đặt bản cập nhật. + Cập nhật + Viết tắt + Cập nhật không thành công + Kiểm tra kết nối Internet của bạn và cập nhật cài đặt proxy để truy cập github-cloud.s3.amazonaws.com. + Bản cập nhật này sẽ khởi động lại Flow Launcher + Các tệp sau sẽ được cập nhật + Cập nhật tệp + mô tả Cập nhật + + + Bỏ qua + Chào mừng bạn đến với Trình khởi chạy luồng + Xin chào, đây là lần đầu tiên bạn sử dụng Flow Launcher! + Trước khi bạn bắt đầu, trình hướng dẫn này sẽ giúp thiết lập Flow Launcher. Bạn có thể bỏ qua điều này nếu bạn muốn. Vui lòng chọn ngôn ngữ + Tìm kiếm và khởi chạy tất cả các tệp và ứng dụng trên PC của bạn + Tìm kiếm mọi thứ từ ứng dụng, tệp, dấu trang, YouTube, Twitter và hơn thế nữa. Tất cả đều từ bàn phím thoải mái mà không cần chạm vào chuột. + Trình khởi chạy Flow bắt đầu bằng phím nóng bên dưới, hãy tiếp tục và dùng thử ngay bây giờ. Để thay đổi nó, hãy nhấp vào đầu vào và nhấn phím nóng mong muốn trên bàn phím. + phím tắt + Từ khóa và lệnh hành động + Tìm kiếm trên web, khởi chạy ứng dụng hoặc chạy các chức năng khác nhau thông qua plugin Flow Launcher. Một số chức năng nhất định bắt đầu bằng từ khóa hành động và nếu cần, chúng có thể được sử dụng mà không cần từ khóa hành động. Hãy thử các truy vấn bên dưới trong Flow Launcher. + Bắt đầu Flow-Launcher + Xong. Thưởng thức Flow Launcher. Đừng quên phím tắt để khởi động Flow Launcher :) + + + + Menu Quay lại / Ngữ cảnh + Mục Điều hướng + Mở menu ngữ cảnh + Mở thư mục chứa + Chạy với tư cách quản trị viên / mở thư mục trong trình quản lý tệp tiêu chuẩn + Lịch sử tìm kiếm + Quay lại kết quả trong menu ngữ cảnh + Tự động hoàn thành + Mở/chạy mục đã chọn + Mở cửa sổ cài đặt + Dữ liệu plugin không tải + + Thời tiết + Thời tiết theo kết quả trên Google + > ping 8.8.8.8 + Lệnh Shell + Bluetooth + Bluetooth trong Cài đặt Windows + sn + Ghi Chú + + + + + From ee17888de6338efa4819291d559e5465e50be25e Mon Sep 17 00:00:00 2001 From: DB p Date: Wed, 24 Apr 2024 04:18:53 +0900 Subject: [PATCH 1248/2008] Delete vi-vn.xaml --- Flow.Launcher/Languages/vi-vn.xaml | 383 ----------------------------- 1 file changed, 383 deletions(-) delete mode 100644 Flow.Launcher/Languages/vi-vn.xaml diff --git a/Flow.Launcher/Languages/vi-vn.xaml b/Flow.Launcher/Languages/vi-vn.xaml deleted file mode 100644 index a54c17df4..000000000 --- a/Flow.Launcher/Languages/vi-vn.xaml +++ /dev/null @@ -1,383 +0,0 @@ - - - - Không thể đăng ký phím nóng "{0}". Phím nóng có thể được sử dụng bởi một chương trình khác. Chuyển sang phím nóng khác hoặc thoát khỏi chương trình khác. - Trình khởi chạy luồng - Không thể khởi động {0} - Định dạng tệp plugin Flow Launcher không chính xác - Đặt ở vị trí hàng đầu trong truy vấn này - Hủy trên cùng trong truy vấn này - Thực thi truy vấn:{0} - Thời gian thực hiện lần cuối:{0} - Mở - Cài đặt - Über - Thoát - Đóng - Sao chép - Di chuyển - Dán - Hoàn tác - Chọn tất cả - Ngày tháng - Thư Mục - Văn bản - Chế độ trò chơi - Tạm dừng sử dụng phím nóng. - Đặt lại vị trí - Đặt lại vị trí của cửa sổ tìm kiếm - - - Cài đặt - Tổng quan - Chế độ Portabler - Lưu trữ tất cả cài đặt và dữ liệu người dùng trong một thư mục (hữu ích khi sử dụng với thiết bị lưu trữ di động hoặc dịch vụ đám mây). - Khởi động Flow Launcher khi khởi động hệ thống - Không lưu được tính năng tự khởi động khi khởi động hệ thống - Ẩn Flow Launcher khi mất tiêu điểm - Không hiển thị thông báo khi có phiên bản mới - Vị trí Suchfenster - Ghi nhớ vị trí cuối cùng - Màn hình bằng con trỏ chuột - Màn hình có cửa sổ được tập trung - Màn hình chính - Màn hình tùy chỉnh - Tìm kiếm vị trí cửa sổ trên màn hình - Trung tâm - Trung tâm trên cùng - Liên kết oben - Trên cùng bên phải - Vị trí tùy chỉnh - Sprache - Chọn kiểu truy vấn - Hiển thị/ẩn các kết quả trước đó khi Flow Launcher được kích hoạt lại. - Giữ lại truy vấn cuối cùng - Chọn truy vấn cuối cùng - Trống truy vấn cuối cùng - Số kết quả tối đa - Có thể thiết lập nhanh chóng bằng CTRL+Plus và CTRL+Minus. - Bỏ qua phím nóng khi cửa sổ ở chế độ toàn màn hình - Tắt Flow Launcher khi ứng dụng toàn màn hình đang hoạt động (Được khuyến nghị để chơi trò chơi). - Trình quản lý ngày tháng tiêu chuẩn - Chọn trình quản lý tệp để sử dụng khi mở thư mục. - Trình duyệt chuẩn - Cài đặt cho tab mới, cửa sổ mới và chế độ riêng tư. - Python-Pfad - Node.js-Pfad - Vui lòng chọn chương trình Node.js - Vui lòng chọn pythonw.exe - Luôn bắt đầu nhập ở chế độ tiếng Anh - Tạm thời chuyển phương thức nhập sang tiếng Anh khi kích hoạt Flow. - Cập nhật tự động - Chọn - Ẩn Trình khởi chạy luồng khi khởi động - Ẩn biểu tượng thanh trạng thái - Khi biểu tượng bị ẩn khỏi khay, bạn có thể mở menu Cài đặt bằng cách nhấp chuột phải vào cửa sổ tìm kiếm. - Độ chính xác của tìm kiếm truy vấn - Kết quả tìm kiếm bắt buộc. - Hoạt động bính âm - Cho phép bạn sử dụng Bính âm để tìm kiếm. Bính âm là hệ thống ký hiệu La Mã tiêu chuẩn để dịch văn bản tiếng Trung. - Luôn xem trước - Luôn mở bảng xem trước khi Flow kích hoạt. Nhấn {0} để chuyển đổi chế độ xem trước. - Hiệu ứng đổ bóng không được phép nếu chủ đề hiện tại bật hiệu ứng làm mờ - - - Plugin tìm kiếm - Ctrl+F để tìm kiếm plugin - Không tìm thấy kết quả nào - Vui lòng thử tìm kiếm khác. - Tiện ích mở rộng - Tiện ích mở rộng - Tìm kiếm thêm plugin - Bật - Tắt - Cài đặt từ hành động - Từ khóa hành động - Từ hành động hiện tại - Từ hành động mới - Thay đổi từ hành động - Ưu tiên hiện tại - Ưu tiên mới - Ưu tiên - Thay đổi mức độ ưu tiên của kết quả plugin - Trình cắm - tác giả - Khởi tạo ban đầu: - Abfragezeit: - Phiên bản - Trang web - Gỡ cài đặt - - - - Tải tiện ích mở rộng - Bản phát hành mới - Cập nhật gần đây - Tiện ích mở rộng - Đã cài đặt - Làm mới - Cài đặt - Gỡ cài đặt - Cập nhật - Plugin đã được cài đặt - Phiên bản mới - Plugin này đã được cập nhật trong vòng 7 ngày qua - Đã có bản cập nhật mới - - - - - Giao Diện - Giao diện - Tìm kiếm thêm chủ đề - Cách tạo chủ đề - Xin chào! - Explorer - Tìm kiếm tệp, thư mục và nội dung tệp - Tìm kiếm trên web - Tìm kiếm trên web với sự hỗ trợ của công cụ tìm kiếm khác - Chương trình - Khởi chạy chương trình với tư cách quản trị viên hoặc người dùng khác - ProcessKiller - Chấm dứt các tiến trình không mong muốn - Phông chữ hộp truy vấn - Phông chữ kết quả - chế độ cửa sổ - độ mờ - Chủ đề {0} không tồn tại nên mẫu mặc định được kích hoạt - Tải chủ đề {0} không thành công, mẫu mặc định được kích hoạt - Mở thư mục chủ đề - Mở thư mục chủ đề - Bảng màu - Mặc định hệ thống - Sáng - Tối - Hiệu ứng âm thanh - Phát âm thanh khi cửa sổ tìm kiếm mở - Âm lượng hiệu ứng âm thanh - Điều chỉnh âm lượng của hiệu ứng âm thanh - Hoạt hình - Sử dụng hình động trong giao diện - Tốc độ hoạt ảnh - Tốc độ của hoạt ảnh giao diện người dùng - Chậm - Trung bình - Nhanh - Tùy chỉnh - Giờ - Ngày - - - Phím tắt - Phím tắt - Phím nóng của Flow Launcher - Nhập phím tắt để hiển thị/ẩn Flow Launcher. - Xem trước phím nóng - Nhập phím tắt để hiển thị/ẩn bản xem trước trong cửa sổ tìm kiếm. - Mở công cụ sửa đổi kết quả - Chọn phím bổ trợ để mở kết quả đã chọn từ bàn phím. - Giải thích phím nóng - Hiển thị phím tắt chọn kết quả cùng với kết quả. - Phím tắt truy vấn tùy chỉnh - Lối tắt truy vấn tùy chỉnh - Phím tắt tích hợp - Truy vấn - Phím tắt - Mở rộng - Mô tả - Xóa - Chỉnh sửa - Thêm - Vui lòng chọn một mục - Bạn có chắc chắn muốn xóa tổ hợp phím plugin {0} không? - Bạn có chắc chắn muốn xóa lối tắt: {0} với phần mở rộng {1} không? - Nhận văn bản từ bảng nhớ tạm. - Nhận đường dẫn từ trình thám hiểm đang hoạt động. - Hiệu ứng đổ bóng trong cửa sổ truy vấn - Hiệu ứng đổ bóng gây rất nhiều áp lực lên GPU. Không nên dùng nếu hiệu suất máy tính của bạn bị hạn chế. - Chiều rộng kích thước cửa sổ - Bạn cũng có thể nhanh chóng điều chỉnh điều này bằng cách sử dụng Ctrl+[ và Ctrl+]. - Sử dụng biểu tượng Segoe - Sử dụng Biểu tượng Segoe Fluent cho kết quả truy vấn nếu được hỗ trợ - Nhấn phím - - - Proxy HTTP - Proxy HTTP hoạt động - Máy chủ HTTP - Cổng - Tài Khoản - Mật khẩu - Proxy thử nghiệm - Lưu - Máy chủ không được để trống - Cổng máy chủ không được để trống - Định dạng cổng Falsches - Proxy đã được lưu thành công - Proxy này được chấp nhận - Kết nối với proxy không thành công - - - Giới thiệu - Trang web - GitHub - Tài liệu - Phiên bản - Biểu tượng - Bạn đã kích hoạt Flow Launcher {0} lần - Kiểm tra các bản cập nhật - Trở thành nhà tài trợ - Đã tồn tại một phiên bản mới ({0}). Vui lòng khởi động lại Flow Launcher. - Kiểm tra cập nhật không thành công. Vui lòng kiểm tra kết nối và cài đặt proxy của bạn tới api.github.com. - - Tải xuống bản cập nhật không thành công. Vui lòng kiểm tra cài đặt kết nối và proxy của bạn tới github-cloud.s3.amazonaws.com, - hoặc truy cập https://github.com/Flow-Launcher/Flow.Launcher/releases để tải xuống các bản cập nhật theo cách thủ công. - - Ghi chú phát hành - Mẹo sử dụng - Công cụ dành cho nhà phát triển - cài đặt thư mục - Thư mục nhật ký - Xóa tệp nhật ký - Bạn có chắc chắn muốn xóa tất cả nhật ký không? - Wizard - - - Chọn trình quản lý tệp - Vui lòng chỉ định vị trí tệp của trình quản lý tệp mà bạn đang sử dụng và thêm đối số nếu cần. Đối số mặc định là "%d" và một đường dẫn được nhập tại vị trí đó. Ví dụ: Nếu một lệnh được yêu cầu như "totalcmd.exe /A c:\windows", đối số là /A "%d". - "%f" là một đối số đại diện cho đường dẫn tệp. Nó được sử dụng để nhấn mạnh tên tệp/thư mục khi mở một vị trí tệp cụ thể trong trình quản lý tệp của bên thứ 3. Đối số này chỉ có sẵn trong phần "Arg for File" mục. Nếu trình quản lý tệp không có chức năng đó, bạn có thể sử dụng "%d". - Trình quản lý ngày tháng - Tên hồ sơ - Đường dẫn quản lý tệp - Đối số cho thư mục - Đối số cho tệp - - - Trình duyệt web tiêu chuẩn - Mặc định sử dụng mặc định trình duyệt của hệ điều hành. Nếu được chỉ định, Flow sẽ sử dụng trình duyệt này. - Trình duyệt - Tên trình duyệt - Đường dẫn trình duyệt - Cửa sổ mới - Thẻ Mới - Chế độ riêng tư - - - Thay đổi mức độ ưu tiên - Số càng cao thì kết quả được xếp hạng càng cao. Hãy thử số 5. ​​Nếu bạn muốn kết quả sâu hơn so với các plugin khác, hãy sử dụng số âm - Vui lòng chỉ định số nguyên hợp lệ cho mức độ ưu tiên! - - - Từ khóa hành động cũ - Từ khóa hành động mới - Viết tắt - Fertig - Không thể tìm thấy plugin được chỉ định - Từ khóa hành động mới không được để trống - Từ khóa hành động đã được một plugin khác sử dụng. Vui lòng đặt từ khóa hành động khác. - Thành công - Đã hoàn tất thành công - Sử dụng * nếu bạn muốn xác định từ khóa hành động. - - - Phím nóng truy vấn tùy chỉnh - Nhấn phím nóng tùy chỉnh để mở Flow Launcher và tự động nhập truy vấn được chỉ định. - Xem trước - Tổ hợp phím không khả dụng, vui lòng chọn tổ hợp phím khác - Tổ hợp phím plugin không hợp lệ - Cập nhật - - - Phím tắt truy vấn tùy chỉnh - Nhập một phím tắt tự động mở rộng theo truy vấn đã chỉ định. - Một phím tắt được mở rộng khi nó khớp chính xác với truy vấn. - -Nếu bạn thêm tiền tố '@' trong khi nhập phím tắt, phím tắt đó sẽ khớp với bất kỳ vị trí nào trong truy vấn. Các phím tắt dựng sẵn khớp với bất kỳ vị trí nào trong truy vấn. - - Phím tắt đã tồn tại, vui lòng nhập Phím tắt mới hoặc chỉnh sửa phím tắt hiện có. - Phím tắt và/hoặc phần mở rộng của nó trống. - - - Tổ hợp phím không khả dụng - - - Phiên bản - Thời gian - Vui lòng cho chúng tôi biết ứng dụng bị lỗi như thế nào để chúng tôi có thể khắc phục lỗi. - Gửi báo cáo - Huỷ bỏ - Chung - Ngoại lệ - Loại ngoại lệ - Nguồn - Ngăn xếp dấu vết - Gửi - Đã gửi báo cáo thành công - Báo cáo lỗi - Trình khởi chạy luồng có lỗi - - - Cảnh báo nhỏ... - - - Kiểm tra cập nhật mới - Bạn đã có phiên bản mới nhất - Tìm thấy cập nhật - Đang cập nhật... - - Flow Launcher không thể di chuyển dữ liệu hồ sơ của bạn sang phiên bản cập nhật mới. - Vui lòng di chuyển thủ công thư mục dữ liệu hồ sơ của bạn từ {0} sang {1} - - Cập nhật mới - Đã có sẵn V{0} của Flow Launcher - Đã xảy ra lỗi khi cài đặt bản cập nhật. - Cập nhật - Viết tắt - Cập nhật không thành công - Kiểm tra kết nối Internet của bạn và cập nhật cài đặt proxy để truy cập github-cloud.s3.amazonaws.com. - Bản cập nhật này sẽ khởi động lại Flow Launcher - Các tệp sau sẽ được cập nhật - Cập nhật tệp - mô tả Cập nhật - - - Bỏ qua - Chào mừng bạn đến với Trình khởi chạy luồng - Xin chào, đây là lần đầu tiên bạn sử dụng Flow Launcher! - Trước khi bạn bắt đầu, trình hướng dẫn này sẽ giúp thiết lập Flow Launcher. Bạn có thể bỏ qua điều này nếu bạn muốn. Vui lòng chọn ngôn ngữ - Tìm kiếm và khởi chạy tất cả các tệp và ứng dụng trên PC của bạn - Tìm kiếm mọi thứ từ ứng dụng, tệp, dấu trang, YouTube, Twitter và hơn thế nữa. Tất cả đều từ bàn phím thoải mái mà không cần chạm vào chuột. - Trình khởi chạy Flow bắt đầu bằng phím nóng bên dưới, hãy tiếp tục và dùng thử ngay bây giờ. Để thay đổi nó, hãy nhấp vào đầu vào và nhấn phím nóng mong muốn trên bàn phím. - phím tắt - Từ khóa và lệnh hành động - Tìm kiếm trên web, khởi chạy ứng dụng hoặc chạy các chức năng khác nhau thông qua plugin Flow Launcher. Một số chức năng nhất định bắt đầu bằng từ khóa hành động và nếu cần, chúng có thể được sử dụng mà không cần từ khóa hành động. Hãy thử các truy vấn bên dưới trong Flow Launcher. - Bắt đầu Flow-Launcher - Xong. Thưởng thức Flow Launcher. Đừng quên phím tắt để khởi động Flow Launcher :) - - - - Menu Quay lại / Ngữ cảnh - Mục Điều hướng - Mở menu ngữ cảnh - Mở thư mục chứa - Chạy với tư cách quản trị viên / mở thư mục trong trình quản lý tệp tiêu chuẩn - Lịch sử tìm kiếm - Quay lại kết quả trong menu ngữ cảnh - Tự động hoàn thành - Mở/chạy mục đã chọn - Mở cửa sổ cài đặt - Dữ liệu plugin không tải - - Thời tiết - Thời tiết theo kết quả trên Google - > ping 8.8.8.8 - Lệnh Shell - Bluetooth - Bluetooth trong Cài đặt Windows - sn - Ghi Chú - - - - - From d2818db6bf5ec36c2a4c5ecc824d83b82e53d71a Mon Sep 17 00:00:00 2001 From: DB p Date: Wed, 24 Apr 2024 04:48:31 +0900 Subject: [PATCH 1249/2008] - Fix Keyboard Navigation Control for Tray Menu - Add Focus Style for toggle --- Flow.Launcher.Infrastructure/Constant.cs | 1 + Flow.Launcher/MainWindow.xaml.cs | 45 ++++++++++++++++-------- Flow.Launcher/SettingWindow.xaml | 44 ++++++++++++++--------- 3 files changed, 59 insertions(+), 31 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Constant.cs b/Flow.Launcher.Infrastructure/Constant.cs index 7a95b52d5..8a95ee79f 100644 --- a/Flow.Launcher.Infrastructure/Constant.cs +++ b/Flow.Launcher.Infrastructure/Constant.cs @@ -7,6 +7,7 @@ namespace Flow.Launcher.Infrastructure public static class Constant { public const string FlowLauncher = "Flow.Launcher"; + public const string FlowLauncherFullName = "Flow Launcher"; public const string Plugins = "Plugins"; public const string PluginMetadataFileName = "plugin.json"; diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 503704046..d7df5a23b 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -27,6 +27,8 @@ using System.Media; using static Flow.Launcher.ViewModel.SettingWindowViewModel; using DataObject = System.Windows.DataObject; using System.Windows.Media; +using System.Windows.Interop; +using System.Runtime.InteropServices; namespace Flow.Launcher { @@ -34,11 +36,14 @@ namespace Flow.Launcher { #region Private Fields + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr SetForegroundWindow(IntPtr hwnd); + private readonly Storyboard _progressBarStoryboard = new Storyboard(); private bool isProgressBarStoryboardPaused; private Settings _settings; private NotifyIcon _notifyIcon; - private ContextMenu contextMenu; + private ContextMenuStrip contextMenu; private MainViewModel _viewModel; private bool _animating; MediaPlayer animationSound = new MediaPlayer(); @@ -258,11 +263,11 @@ namespace Flow.Launcher private void UpdateNotifyIconText() { var menu = contextMenu; - ((MenuItem)menu.Items[0]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")"; - ((MenuItem)menu.Items[1]).Header = InternationalizationManager.Instance.GetTranslation("GameMode"); - ((MenuItem)menu.Items[2]).Header = InternationalizationManager.Instance.GetTranslation("PositionReset"); - ((MenuItem)menu.Items[3]).Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"); - ((MenuItem)menu.Items[4]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"); + //((MenuItem)menu.Items[0]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")"; + //((MenuItem)menu.Items[1]).Header = InternationalizationManager.Instance.GetTranslation("GameMode"); + //((MenuItem)menu.Items[2]).Header = InternationalizationManager.Instance.GetTranslation("PositionReset"); + //((MenuItem)menu.Items[3]).Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"); + //((MenuItem)menu.Items[4]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"); } @@ -270,12 +275,12 @@ namespace Flow.Launcher { _notifyIcon = new NotifyIcon { - Text = Infrastructure.Constant.FlowLauncher, + Text = Infrastructure.Constant.FlowLauncherFullName, Icon = Properties.Resources.app, Visible = !_settings.HideNotifyIcon }; - contextMenu = new ContextMenu(); + var contextMenu = new ContextMenu(); var openIcon = new FontIcon { @@ -283,7 +288,8 @@ namespace Flow.Launcher }; var open = new MenuItem { - Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")", Icon = openIcon + Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")", + Icon = openIcon }; var gamemodeIcon = new FontIcon { @@ -291,7 +297,8 @@ namespace Flow.Launcher }; var gamemode = new MenuItem { - Header = InternationalizationManager.Instance.GetTranslation("GameMode"), Icon = gamemodeIcon + Header = InternationalizationManager.Instance.GetTranslation("GameMode"), + Icon = gamemodeIcon }; var positionresetIcon = new FontIcon { @@ -299,7 +306,8 @@ namespace Flow.Launcher }; var positionreset = new MenuItem { - Header = InternationalizationManager.Instance.GetTranslation("PositionReset"), Icon = positionresetIcon + Header = InternationalizationManager.Instance.GetTranslation("PositionReset"), + Icon = positionresetIcon }; var settingsIcon = new FontIcon { @@ -307,7 +315,8 @@ namespace Flow.Launcher }; var settings = new MenuItem { - Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"), Icon = settingsIcon + Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"), + Icon = settingsIcon }; var exitIcon = new FontIcon { @@ -315,7 +324,8 @@ namespace Flow.Launcher }; var exit = new MenuItem { - Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"), Icon = exitIcon + Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"), + Icon = exitIcon }; open.Click += (o, e) => _viewModel.ToggleFlowLauncher(); @@ -333,7 +343,6 @@ namespace Flow.Launcher contextMenu.Items.Add(settings); contextMenu.Items.Add(exit); - _notifyIcon.ContextMenuStrip = new ContextMenuStrip(); // it need for close the context menu. if not, context menu can't close. _notifyIcon.MouseClick += (o, e) => { switch (e.Button) @@ -341,9 +350,15 @@ namespace Flow.Launcher case MouseButtons.Left: _viewModel.ToggleFlowLauncher(); break; - case MouseButtons.Right: + contextMenu.IsOpen = true; + // Get context menu handle and bring it to the foreground + if (PresentationSource.FromVisual(contextMenu) is HwndSource hwndSource) + { + _ = SetForegroundWindow(hwndSource.Handle); + } + contextMenu.Focus(); break; } }; diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 96f80f0c5..00de0512c 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -67,6 +67,20 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + - - - - + + + + + + + + @@ -609,1579 +212,2195 @@ Grid.Row="0" Width="50" Height="50" + RenderOptions.BitmapScalingMode="HighQuality" Source="images/app.png" /> + TextAlignment="Center" /> - - - - - - - - - - - -  - - - - - - - - - - - - - - - - -  - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - -  - - - - - - - - - - - - -  - - - - - - - - - - - -  - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + +  + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - - - - - - - -  - - - - - - - + - - + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + +  + + + + + - - - - - - - - -  - - - - - + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + +  + + + + + + + + + + - - - -  - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - -  - - - - - - + Click="OnTestProxyClick" + Content="{DynamicResource testProxy}" + IsEnabled="{Binding Settings.Proxy.Enabled}" /> + + + + - - - - - + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + +  + + + + + + + + + + + + + diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index 8144c8ff8..0bba24997 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -24,6 +24,7 @@ using KeyEventArgs = System.Windows.Input.KeyEventArgs; using MessageBox = System.Windows.MessageBox; using TextBox = System.Windows.Controls.TextBox; using ThemeManager = ModernWpf.ThemeManager; +using Flow.Launcher.SettingPages.Views; namespace Flow.Launcher { @@ -503,5 +504,28 @@ namespace Flow.Launcher { Keyboard.Focus(pluginFilterTxb); } + + /** For Navigation View **/ + private void NavigationView_SelectionChanged(ModernWpf.Controls.NavigationView sender, ModernWpf.Controls.NavigationViewSelectionChangedEventArgs args) + { + if (args.IsSettingsSelected) + { + contentFrame.Navigate(typeof(General)); + } + else + { + var selectedItem = (ModernWpf.Controls.NavigationViewItem)args.SelectedItem; + if (selectedItem == null) + { + return; + } + string selectedItemTag = (string)selectedItem.Tag; + + sender.Header = (string)selectedItem.Content; + string pageName = $"Flow.Launcher.SettingPages.Views.{selectedItemTag}"; + Type pageType = typeof(About).Assembly.GetType(pageName); + contentFrame.Navigate(pageType, settings); + } + } } } diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index fe1ea4e7b..efd37b0e1 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -24,6 +24,7 @@ using CommunityToolkit.Mvvm.Input; using System.Globalization; using System.Runtime.CompilerServices; using Flow.Launcher.Infrastructure.Hotkey; +using ModernWpf.Media.Animation; namespace Flow.Launcher.ViewModel { @@ -33,6 +34,12 @@ namespace Flow.Launcher.ViewModel private readonly IPortable _portable; private readonly FlowLauncherJsonStorage _storage; + /* For Navigation View */ + private NavigationTransitionInfo _transitionInfo = new SlideNavigationTransitionInfo() + { + Effect = SlideNavigationTransitionEffect.FromBottom + }; + public SettingWindowViewModel(Updater updater, IPortable portable) { _updater = updater; From b4570e9aaa497037abb8e97be2c3cf8ded7bc723 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 27 Apr 2024 21:57:55 +0900 Subject: [PATCH 1269/2008] - Add Pages --- Flow.Launcher/Flow.Launcher.csproj | 4 - .../Resources/SettingWindowStyle.xaml | 4 + Flow.Launcher/SettingPages/General.xaml | 19 - Flow.Launcher/SettingPages/General.xaml.cs | 22 - .../ViewModels/GeneralViewModel.cs | 49 +- Flow.Launcher/SettingPages/Views/About.xaml | 232 ++ .../SettingPages/Views/About.xaml.cs | 37 + Flow.Launcher/SettingPages/Views/General.xaml | 517 +++ .../SettingPages/Views/General.xaml.cs | 51 + Flow.Launcher/SettingPages/Views/Hotkey.xaml | 471 +++ .../SettingPages/Views/Hotkey.xaml.cs | 28 + .../SettingPages/Views/PluginStore.xaml | 347 ++ .../SettingPages/Views/PluginStore.xaml.cs | 28 + Flow.Launcher/SettingPages/Views/Plugins.xaml | 384 +++ .../SettingPages/Views/Plugins.xaml.cs | 28 + Flow.Launcher/SettingPages/Views/Proxy.xaml | 180 + .../SettingPages/Views/Proxy.xaml.cs | 28 + Flow.Launcher/SettingPages/Views/Theme.xaml | 744 +++++ .../SettingPages/Views/Theme.xaml.cs | 25 + Flow.Launcher/SettingWindow.xaml | 2933 ----------------- Flow.Launcher/SettingWindow.xaml.cs | 166 +- .../ViewModel/SettingWindowViewModel.cs | 23 - 22 files changed, 3235 insertions(+), 3085 deletions(-) delete mode 100644 Flow.Launcher/SettingPages/General.xaml delete mode 100644 Flow.Launcher/SettingPages/General.xaml.cs create mode 100644 Flow.Launcher/SettingPages/Views/About.xaml create mode 100644 Flow.Launcher/SettingPages/Views/About.xaml.cs create mode 100644 Flow.Launcher/SettingPages/Views/General.xaml create mode 100644 Flow.Launcher/SettingPages/Views/General.xaml.cs create mode 100644 Flow.Launcher/SettingPages/Views/Hotkey.xaml create mode 100644 Flow.Launcher/SettingPages/Views/Hotkey.xaml.cs create mode 100644 Flow.Launcher/SettingPages/Views/PluginStore.xaml create mode 100644 Flow.Launcher/SettingPages/Views/PluginStore.xaml.cs create mode 100644 Flow.Launcher/SettingPages/Views/Plugins.xaml create mode 100644 Flow.Launcher/SettingPages/Views/Plugins.xaml.cs create mode 100644 Flow.Launcher/SettingPages/Views/Proxy.xaml create mode 100644 Flow.Launcher/SettingPages/Views/Proxy.xaml.cs create mode 100644 Flow.Launcher/SettingPages/Views/Theme.xaml create mode 100644 Flow.Launcher/SettingPages/Views/Theme.xaml.cs diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index c280c3c7e..53c1bafc7 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -111,10 +111,6 @@ - - - - diff --git a/Flow.Launcher/Resources/SettingWindowStyle.xaml b/Flow.Launcher/Resources/SettingWindowStyle.xaml index 97671b088..485a0159d 100644 --- a/Flow.Launcher/Resources/SettingWindowStyle.xaml +++ b/Flow.Launcher/Resources/SettingWindowStyle.xaml @@ -20,6 +20,10 @@ + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + +  + + + + + + + + + + + + +  + + + + + + + + + + + +  + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + diff --git a/Flow.Launcher/SettingPages/Views/PluginStore.xaml.cs b/Flow.Launcher/SettingPages/Views/PluginStore.xaml.cs new file mode 100644 index 000000000..3d756f6fa --- /dev/null +++ b/Flow.Launcher/SettingPages/Views/PluginStore.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Flow.Launcher.SettingPages.Views +{ + /// + /// PluginStore.xaml에 대한 상호 작용 논리 + /// + public partial class PluginStore : Page + { + public PluginStore() + { + InitializeComponent(); + } + } +} diff --git a/Flow.Launcher/SettingPages/Views/Plugins.xaml b/Flow.Launcher/SettingPages/Views/Plugins.xaml new file mode 100644 index 000000000..d0545de11 --- /dev/null +++ b/Flow.Launcher/SettingPages/Views/Plugins.xaml @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - -  - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - -  - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - -  - - - - - - - - - - - - diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index 0bba24997..8f3edc872 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -42,7 +42,7 @@ namespace Flow.Launcher API = api; InitializePosition(); InitializeComponent(); - + NavView.SelectedItem = NavView.MenuItems[0]; /* Set First Page */ } #region General @@ -54,28 +54,28 @@ namespace Flow.Launcher // https://stackoverflow.com/questions/4951058/software-rendering-mode-wpf HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; HwndTarget hwndTarget = hwndSource.CompositionTarget; - hwndTarget.RenderMode = RenderMode.SoftwareOnly; + hwndTarget.RenderMode = RenderMode.Default; - pluginListView = (CollectionView)CollectionViewSource.GetDefaultView(Plugins.ItemsSource); - pluginListView.Filter = PluginListFilter; + //pluginListView = (CollectionView)CollectionViewSource.GetDefaultView(Plugins.ItemsSource); + //pluginListView.Filter = PluginListFilter; - pluginStoreView = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource); - pluginStoreView.Filter = PluginStoreFilter; + //pluginStoreView = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource); + //pluginStoreView.Filter = PluginStoreFilter; - viewModel.PropertyChanged += new PropertyChangedEventHandler(SettingsWindowViewModelChanged); + //viewModel.PropertyChanged += new PropertyChangedEventHandler(SettingsWindowViewModelChanged); InitializePosition(); } - private void SettingsWindowViewModelChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(viewModel.ExternalPlugins)) - { - pluginStoreView = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource); - pluginStoreView.Filter = PluginStoreFilter; - pluginStoreView.Refresh(); - } - } + //private void SettingsWindowViewModelChanged(object sender, PropertyChangedEventArgs e) + //{ + // if (e.PropertyName == nameof(viewModel.ExternalPlugins)) + // { + // pluginStoreView = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource); + // pluginStoreView.Filter = PluginStoreFilter; + // pluginStoreView.Refresh(); + // } + //} private void OnSelectPythonPathClick(object sender, RoutedEventArgs e) { @@ -375,75 +375,75 @@ namespace Flow.Launcher private CollectionView pluginListView; private CollectionView pluginStoreView; - private bool PluginListFilter(object item) - { - if (string.IsNullOrEmpty(pluginFilterTxb.Text)) - return true; - if (item is PluginViewModel model) - { - return StringMatcher.FuzzySearch(pluginFilterTxb.Text, model.PluginPair.Metadata.Name).IsSearchPrecisionScoreMet(); - } - return false; - } + //private bool PluginListFilter(object item) + //{ + // if (string.IsNullOrEmpty(pluginFilterTxb.Text)) + // return true; + // if (item is PluginViewModel model) + // { + // return StringMatcher.FuzzySearch(pluginFilterTxb.Text, model.PluginPair.Metadata.Name).IsSearchPrecisionScoreMet(); + // } + // return false; + //} - private bool PluginStoreFilter(object item) - { - if (string.IsNullOrEmpty(pluginStoreFilterTxb.Text)) - return true; - if (item is PluginStoreItemViewModel model) - { - return StringMatcher.FuzzySearch(pluginStoreFilterTxb.Text, model.Name).IsSearchPrecisionScoreMet() - || StringMatcher.FuzzySearch(pluginStoreFilterTxb.Text, model.Description).IsSearchPrecisionScoreMet(); - } - return false; - } + //private bool PluginStoreFilter(object item) + //{ + // if (string.IsNullOrEmpty(pluginStoreFilterTxb.Text)) + // return true; + // if (item is PluginStoreItemViewModel model) + // { + // return StringMatcher.FuzzySearch(pluginStoreFilterTxb.Text, model.Name).IsSearchPrecisionScoreMet() + // || StringMatcher.FuzzySearch(pluginStoreFilterTxb.Text, model.Description).IsSearchPrecisionScoreMet(); + // } + // return false; + //} private string lastPluginListSearch = ""; private string lastPluginStoreSearch = ""; - private void RefreshPluginListEventHandler(object sender, RoutedEventArgs e) - { - if (pluginFilterTxb.Text != lastPluginListSearch) - { - lastPluginListSearch = pluginFilterTxb.Text; - pluginListView.Refresh(); - } - } + //private void RefreshPluginListEventHandler(object sender, RoutedEventArgs e) + //{ + // if (pluginFilterTxb.Text != lastPluginListSearch) + // { + // lastPluginListSearch = pluginFilterTxb.Text; + // pluginListView.Refresh(); + // } + //} - private void RefreshPluginStoreEventHandler(object sender, RoutedEventArgs e) - { - if (pluginStoreFilterTxb.Text != lastPluginStoreSearch) - { - lastPluginStoreSearch = pluginStoreFilterTxb.Text; - pluginStoreView.Refresh(); - } - } + //private void RefreshPluginStoreEventHandler(object sender, RoutedEventArgs e) + //{ + // if (pluginStoreFilterTxb.Text != lastPluginStoreSearch) + // { + // lastPluginStoreSearch = pluginStoreFilterTxb.Text; + // pluginStoreView.Refresh(); + // } + //} - private void PluginFilterTxb_OnKeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Enter) - RefreshPluginListEventHandler(sender, e); - } + //private void PluginFilterTxb_OnKeyDown(object sender, KeyEventArgs e) + //{ + // if (e.Key == Key.Enter) + // RefreshPluginListEventHandler(sender, e); + //} - private void PluginStoreFilterTxb_OnKeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Enter) - RefreshPluginStoreEventHandler(sender, e); - } + //private void PluginStoreFilterTxb_OnKeyDown(object sender, KeyEventArgs e) + //{ + // if (e.Key == Key.Enter) + // RefreshPluginStoreEventHandler(sender, e); + //} - private void OnPluginSettingKeydown(object sender, KeyEventArgs e) - { - if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control && e.Key == Key.F) - pluginFilterTxb.Focus(); - } + //private void OnPluginSettingKeydown(object sender, KeyEventArgs e) + //{ + // if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control && e.Key == Key.F) + // pluginFilterTxb.Focus(); + //} - private void PluginStore_OnKeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.F && (Keyboard.Modifiers & ModifierKeys.Control) != 0) - { - pluginStoreFilterTxb.Focus(); - } - } + //private void PluginStore_OnKeyDown(object sender, KeyEventArgs e) + //{ + // if (e.Key == Key.F && (Keyboard.Modifiers & ModifierKeys.Control) != 0) + // { + // pluginStoreFilterTxb.Focus(); + // } + //} public void InitializePosition() { @@ -495,15 +495,15 @@ namespace Flow.Launcher } - private void PluginStore_GotFocus(object sender, RoutedEventArgs e) - { - Keyboard.Focus(pluginStoreFilterTxb); - } + //private void PluginStore_GotFocus(object sender, RoutedEventArgs e) + //{ + // Keyboard.Focus(pluginStoreFilterTxb); + //} - private void Plugin_GotFocus(object sender, RoutedEventArgs e) - { - Keyboard.Focus(pluginFilterTxb); - } + //private void Plugin_GotFocus(object sender, RoutedEventArgs e) + //{ + // Keyboard.Focus(pluginFilterTxb); + //} /** For Navigation View **/ private void NavigationView_SelectionChanged(ModernWpf.Controls.NavigationView sender, ModernWpf.Controls.NavigationViewSelectionChangedEventArgs args) diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index efd37b0e1..aa16e7cb7 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -481,29 +481,6 @@ namespace Flow.Launcher.ViewModel } } - public class SearchWindowScreen - { - public string Display { get; set; } - public SearchWindowScreens Value { get; set; } - } - - public List SearchWindowScreens - { - get - { - List modes = new List(); - var enums = (SearchWindowScreens[])Enum.GetValues(typeof(SearchWindowScreens)); - foreach (var e in enums) - { - var key = $"SearchWindowScreen{e}"; - var display = _translater.GetTranslation(key); - var m = new SearchWindowScreen { Display = display, Value = e, }; - modes.Add(m); - } - - return modes; - } - } public class SearchWindowAlign { From 6a2f23cf6bb22707280c2d681243ea6fc30b8bc5 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 27 Apr 2024 22:48:03 +0900 Subject: [PATCH 1270/2008] - Add Color Icons in Menu --- Flow.Launcher/Images/info.png | Bin 0 -> 1367 bytes Flow.Launcher/Images/keyboard.png | Bin 0 -> 873 bytes Flow.Launcher/Images/plugins.png | Bin 0 -> 804 bytes Flow.Launcher/Images/proxy.png | Bin 0 -> 1757 bytes Flow.Launcher/Images/store.png | Bin 0 -> 763 bytes Flow.Launcher/Images/theme.png | Bin 0 -> 1071 bytes .../Resources/CustomControlTemplate.xaml | 4 +++- Flow.Launcher/SettingWindow.xaml | 14 +++++++------- 8 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 Flow.Launcher/Images/info.png create mode 100644 Flow.Launcher/Images/keyboard.png create mode 100644 Flow.Launcher/Images/plugins.png create mode 100644 Flow.Launcher/Images/proxy.png create mode 100644 Flow.Launcher/Images/store.png create mode 100644 Flow.Launcher/Images/theme.png diff --git a/Flow.Launcher/Images/info.png b/Flow.Launcher/Images/info.png new file mode 100644 index 0000000000000000000000000000000000000000..75ffe11e0e80ad0abda0b0c6be6bf4fbec510a10 GIT binary patch literal 1367 zcmV-d1*rOoP)e~1+`))7_;wTGnkk_g98p=tV&f=wH13HFy2=%nPJAMqM#@$Uo}43 zQ3uZ(tRDDFa~=JDZ{GLj`yPf}>eJEtKhxS4$U2OYs6} zEuJS=i*>~PA|26Ms3ShkyGN#D|A$oRyn^y&`kKN(|5mYdd|JLlLHQyDW%rMvRDTR5 z3nY}xlTdt*fFd0Mg>wWH-hB)OKR*Wf?9pEZcaFZ4-z8!r4ql{%*DH zu}ndj@F1T#g8Vy2kT>n4a<#r28Cq9#MBo*MCvPiO=sm>>4Lra@uGR;+w+}(4Ik3qz zzIV?RzS2m4qgbI|@C~0c#RwdNY|{IWRPFr{1Bl|693ZOF=x?bs`r-WG4?sF`0NH9U zNX9+ts=n3Nc;l}!`c;vG_kv{13t1y>4OR`W@B#l_#NkIhkU8RkjA2&;61>7ly~B0S z%e8LEQ=1`g+zfdd7YBGZWDL1Z(}q0nbAr#+!=*|ijdOu7(%3-#hyd#3Mc^6VAs~O; z5+3|5H>3}_A#Kp*lMLH0hb>UK;=jRZ<)=MR^Tz=M=cfl=kf~ka!b94C3sUd82TfugzW`TQv-OgpV&7aHgGEKw+T2=321%S}$B%c7zCg zqPK%|+!Z#wxGx|8qHagcnFT7A=`EDgCP!_9&zBr<7bgSHrwshCg*$wY15&yi&NCgW zWripDyd0Gp56DJsARV!ROzlR3ztYVJ*dejg_7?l<8>lZ(;d92UkUg*qlKx$g^zA@a z?+!?Y%t-LbopwlWw|>w51s0EoQGZeld~hUY#XEVJq%0$tlk z@Ja19NKje#*ah^Y6SX~%^gav`$mrZcf=_H?1T0Tk1xocKh1%O>^@IwfcWfcSC#tNF zptPJ~T6pz81&ZehKWbx^*}WYikk+w@2H$Fh%SsDiY;AVQJn2R4DqkwlzKIMU-(o&t z-9p7WVgt1$W(qbqscoBx@D_+`Hal4bispzZ)P9~R*x-m&8%Xf+%@&AlG%v9V6wDFd zq7EZW!G;L5ZXm(OHJKTKM)of-OI}5tq?m#Yj!3zV3J-z?^LwlU%rPaO^?A6Df$l)T z2Ior4Iug9F0rz9o_BYrCFbtE=_!_ywGe;#;u)#^Wxy~6rrojZldVCN&Yh+q)R_?U# zITv{5sALK@M4)+%Gki=Pek!cpFT=t~&TZcc&GQ*0Lp#n)w>m1?nXP4@6S=a&ri3#6loMzaLy}+JlwhgoLNsVieq}&Z3zRm=K z8vHtjl5F+CB95o!1?SP;GYX>@E>@&k!Fji-ys$E zIcLSaj#GZ%@x_?h{Q@k~N$Ihbi+b#1Dc$y`;ltx6G4-aY=sKMJuIJoEI(K3cyX+q% zx7#|C+H8L&s%-wyVZ`!xY@=y4w!zdVtlR(a{PsCd5j7tQg(|B^pmd}%f_%OAA{W8< Z&A)|h%;wC=< literal 0 HcmV?d00001 diff --git a/Flow.Launcher/Images/keyboard.png b/Flow.Launcher/Images/keyboard.png new file mode 100644 index 0000000000000000000000000000000000000000..5ac670419ab080f24aa88343a1054b92c78827d3 GIT binary patch literal 873 zcmV-v1D5=WP)lA4u5iug3Q!I*7lj{uF8>Mu9uXVhb9r;Q7U%!wqR{>T1Lb@3{2lV&A7TJ# z0+A|n{tajXk!t_!E6@ZYRr>S`&;%mY-pOa62}G*Y@h6}OM5^S`NBCDvxmYmS-h(&D zJ@_{esdf)PfLtP}6L_kshsx?YsM9qAm%S{h8#;P$?VXDib3%_VmXlqxw zdEw{?anZo|^a75(!34hemA5@pbDn!=2@o3ybBAyr^Q<5AhEB|8WUr()x9r3D#+O~V z_L?z)wy6yqE>`R@S{?WWJga?y?}pSoVgsR_EYJiZRWOkOnn0uyz92M#Nac_115F@O z`J!o{2}CO4>p>HUR4aivY-}Z|fZdFe8*t3CupZu}0{e`c+yFCd!GAogF9vHNt}J*q zB6#_}Av3vwzF`Z{1R_|J5t5(H&4L_ik= zFw<>mo9a0(o97~L?p;8#b1c&G}C{O)1jJXyjX{3e45ozu!NOo;l1oL^IX^i zpYO7~0}h8h_Sj>OJuRF2+qbyEtsQP~8@RzO;08V%EE(7YqL+Z^8$e>l7J)?9!5Lix zXTPzl;OtxZyUW091>m(M;3LK^0^j={_}+IQ+%t9ogr2vD8=eOt{078u9)#}vju_0} zMETKptuegVZEOyNVD>XIfE`{8y#_Iq1?(qqjMtlipRb7*gV=yGG}aAR{CCj+N|%B{# zSN0`tpX-=DPko7JWxTn7^2FBUlP?|O7n+KfJ0?Nym;l*lYyv9rF3%|L*C=be%k#>D z0ET#1`v@|CG2Vp_Xd&M7FJ5uKL1P)rh&w_ldV0?z(=5`#3_XsDqu$R$j|h18W&q=`mQSj>1xM z6h$S~Os;Aax~foET!n(-N+xF|%uY9xqXPLv_HwEtM7A=jJXBmV( zKTks1GXW`W0@B_INa^E{_Kia(+CL8Y0MQsTU~%E`41DkqE7mRmzIhtPZ>C|~ItAnQ zsW9{|E%YR$p9u7PU|E139D{sl4Dw;3QOFsikTaQbEiUp8Jca=RzHSbNPYC$z0^qu| zck`sR(CHH_;d#KLAy7GM6ms@$$T?iOOgYOjK>AKoCw2LF4u*}hFnp$|iXL2>wy1|l zS_@4Q&d|Z;GAVhtpd7gcC7;VoG(zEXii)E*ATC&17n=GE44==y_@$=fqACl4i+U^q zt!RPGBTx!PpcIZkDIyw%Vqqfi*~>DpQCF8O)9m8ZRwV?kOPka~^jJXW-Ch8An88|y zq1cFqpxB3CaxfA2?7~%mFdB55tONH_#M6oz#U!BjlR zPErp;iT% zs)H0hs~}bbWi_lashZS77w9OYv_7n@9zplm14svYG>LO?ecB>vp0aH7pnGx->(2GV zRJ-2wGz57fFosC5CT z$GJ`fD12rt2E;uMt&HgUzHvzDgLpkZh?e15EHzF2(~vFQkZs*)8kk!0^Pb5WtUlER zQ%yJ2lK~{w_cHy`%M6%fHgJqpX72>s=ZD5%O!vb-@c_||Z0msR=!p9By;E~A9cxG8 zsa_?4)j4b^RG!9Ndadko|?L^a16#u}T8LU3j z3AMfxiNE@hc!ujYV!$4o0dZ?g*CRPa`G%nv>5%~>=lW1^eLVEzN)2kgi`3kx`qL|Nfc`*U4v>RTYGei)bfk*L?GO0QH=&aOtr1>-kZhx zD*>qW?MOW9rLa`zdyw>pkEzjzjQp4lum_V6d_IRKtI;;h)}m_=io*}t)&-^1A2qnB zg?icpQ++Gc22U8ck*mpvqzgn|BsF^}d~62zQ`MvJ{2(IxoSc?4^?tUy`Oc=RZxL`> z4{geg8sKIIoOF@vPbLC?_=q)n1LBd8!iz(R97s-n_mz>C!D19bI81%AO7 z0k|7Um$)u75%|~*xT+(=mveY+W%Q{x^s-G730#}@MIAH;PQF6a#dNi683y>ncnF@{ z29yje4zEvLY?8&mFGYa9%5^QQm<@pZZeZ*Sa17PX3$7gX9|?ti0h_h5`N(YTgCAApHEwB%Rl!t_Qyy z0sQ)WXac;lMWfb^*bSJS?%*=tpwV|Y;ysRd7#EL(^udJR8jBmWOmfQdlUA(D$g)KL zV$1BRTw`{)gE7BBv+ChpOTuT)gI~yirSD+A?ahQ|Ih%LwfmR9swb>ju@RVoO_V$ab zcH9Kj&UU=2(JNGKR4=E5^-@Y}NG}ql61CuklpD=Y_3w|Q*982NFp%1Ux8Hde@2%g2 z4VzOI{LTN5foNvcj`rq%ZH3|!pZLTl;aSZ;fr-kPN32xC00000NkvXXu0mjfpb<|o literal 0 HcmV?d00001 diff --git a/Flow.Launcher/Images/store.png b/Flow.Launcher/Images/store.png new file mode 100644 index 0000000000000000000000000000000000000000..a4b19c8f9337fd4f8282973b7dbe19defa593be5 GIT binary patch literal 763 zcmVwF@z3GK^8{ODX&W3rAi&0PGf(gh5Y)sf- zc;v<^Q#MCSNaUi)#*Yj(9SFi0@gESv0S3mz1Bw3uXX8l|V?e*AXlHG@bnUWtn7mK& zIXz3C_tU<~5F#NVA^GofqcnZgemD&pDPcKWG{N18Cb)xWg8RxQcu+#e;m=_!JWtq) z#`*n+lhe0rK0KS?&MFPnOMorIoz)~Eym|GJdJ6CmjdSm75s+M)8CRv>3HMpEK#4!7 z^gLnfuK@pDw}A9b=zd5ew^<^fKP>qIh+LtX!jdb55E>hgfe6B!F}>SuJF$iKlKy|! zx>4f6y)&_-D&XFG{Gs88JygcM_vl#t3+%==FRZ|BY+F^}+U~@7qYv6%fws5oq^f{@ zd)U^x{Qxc^uEI#GssI9X$+Z>v;wp~9MZ#Ge{f0R1vbq35$We$KI|~s|f=T&+n(6>1 z?ZwhL%Zz-i>hR~+Xd_&7Yz~7GbkYOV6A#c+9auU?nedyc1#Ii#8T;!nC?O1q;OOik z>*1%>3#^5PZR;UWLOO<{v;D!k7K&6aurhSh`f3Q2kdEQ#tRicnTU84~fBOSxhF#^l}gl2)}jIY0WsSo5x$8dDb0vTVw z_Ajv5cioif1v%0&9GxlC3&L463)r9guNW7-Ka7h$kV1)n`$-Sr=!^@#pDoK>SCO6= z=DjC|c`rzzXFGvPb^twl7jSfjdG86*8!CNoi=OL&MncW?6m$#F&w3n9sqOIw&H4ZU002ovPDHLkV1hVaWcC06 literal 0 HcmV?d00001 diff --git a/Flow.Launcher/Images/theme.png b/Flow.Launcher/Images/theme.png new file mode 100644 index 0000000000000000000000000000000000000000..9518343b7fe7f827d3c084c01bab9889257acdf1 GIT binary patch literal 1071 zcmV+~1kn45P)&+o!$oH5zeW;8OvWXsGHEn!LqlDdwJ zvNh8XmPO;(#is6%U8pl-W^p9jE<{sjYGetp4rb{%qy@?*g%%jama@$Qd&xB zY3X_WnqC-(imPkWr^J5#fG4kap6_$>0GVZ$S!T(Yck7NL9%02kEX8@YY!}Q4w@2Ki zi)T~sK`rr}zX-$6YY-lovcf*p!Tf?;-{e~L_eL7R{ ze)wQKpmC8p`53k2cS1syhB`h#2X5_44G;@;CbTuRUQAW1IjK2Ts?M3ltTe`y1 z=FUUlVjd~@?t0kVr$H_Wqs0QIK45hD)LVbYw|3d3as{6g{QNnr_cX#g*8qwqzlQhW9A2V!jRjL;}o}tckM#p8_BI+CT{f>|#G~7ofzoBm~TIf)94%IlmH= za6lysaT4HH;aD;PCU!9!R{=MZ6fl@_d`OMLKsP8U0hO#eyh zp8D}bK#gFM-hc$DUQmluK{Y7R0LxxB=Gc$NQ;PRrLQYVNU=jkxC-&nhqPPSjM0bz zbiV+1J;Lr<=v@+4;}k>W5U2PfU2J!+peL+HFmwsFkQTQBJ@_u5!UdlKr+sbs$Rk7f pd=q#!IUZZ|A(>^CS!Vx>{SLrHrRuzJJ*fZy002ovPDHLkV1in_16cq7 literal 0 HcmV?d00001 diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index e52143fa5..17a9f1f64 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -3697,6 +3697,8 @@ + 48 + + 48 diff --git a/Flow.Launcher/Resources/SettingWindowStyle.xaml b/Flow.Launcher/Resources/SettingWindowStyle.xaml index 485a0159d..97671b088 100644 --- a/Flow.Launcher/Resources/SettingWindowStyle.xaml +++ b/Flow.Launcher/Resources/SettingWindowStyle.xaml @@ -20,10 +20,6 @@ - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs index b2839231e..60e4a31b4 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs @@ -10,6 +10,7 @@ using Flow.Launcher.Plugin.Explorer.Search.Everything; using System.Windows.Input; using System.Windows.Shapes; using Path = System.IO.Path; +using System.Globalization; namespace Flow.Launcher.Plugin.Explorer.Search { @@ -189,11 +190,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search if (mok == 1) uom = "KB"; else if (mok == 2) - uom = " MB"; + uom = "MB"; else if (mok == 3) - uom = " GB"; + uom = "GB"; else if (mok == 4) - uom = " TB"; + uom = "TB"; var returnStr = $"{Convert.ToInt32(drvSize)}{uom}"; if (mok != 0) @@ -241,14 +242,16 @@ namespace Flow.Launcher.Plugin.Explorer.Search var title = Path.GetFileName(filePath); + /* Preview Detail */ long fileSize = new System.IO.FileInfo(filePath).Length; - string fileSizStr = fileSize.ToString(); + string fileSizStr = ToReadableSize(fileSize, 2); DateTime created = System.IO.File.GetCreationTime(filePath); - string createdStr = created.ToString("yyyy-MM-dd HH:mm:ss"); + string createdStr = created.ToString("yy-M-dd ddd hh:mm", CultureInfo.CurrentCulture); DateTime lastModified = System.IO.File.GetLastWriteTime(filePath); - string lastModifiedStr = lastModified.ToString("yyyy-MM-dd HH:mm:ss"); + string lastModifiedStr = lastModified.ToString("yy-M-dd ddd hh:mm", CultureInfo.CurrentCulture); + var result = new Result From 08687d63cb3511b45a791ea49b5d4e87d41c6d79 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Tue, 30 Apr 2024 09:16:43 +0600 Subject: [PATCH 1288/2008] Implement CardGroup control --- Flow.Launcher/Resources/Controls/Card.xaml | 21 +++++++++++++ Flow.Launcher/Resources/Controls/Card.xaml.cs | 17 ++++++++++ .../Resources/Controls/CardGroup.xaml | 31 +++++++++++++++++++ .../Resources/Controls/CardGroup.xaml.cs | 25 +++++++++++++++ .../Controls/CardGroupCardStyleSelector.cs | 21 +++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 Flow.Launcher/Resources/Controls/CardGroup.xaml create mode 100644 Flow.Launcher/Resources/Controls/CardGroup.xaml.cs create mode 100644 Flow.Launcher/Resources/Controls/CardGroupCardStyleSelector.cs diff --git a/Flow.Launcher/Resources/Controls/Card.xaml b/Flow.Launcher/Resources/Controls/Card.xaml index bc1c42e1f..147c0e650 100644 --- a/Flow.Launcher/Resources/Controls/Card.xaml +++ b/Flow.Launcher/Resources/Controls/Card.xaml @@ -37,6 +37,27 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Flow.Launcher/Resources/Controls/Card.xaml.cs b/Flow.Launcher/Resources/Controls/Card.xaml.cs index 06266c775..db4a136a3 100644 --- a/Flow.Launcher/Resources/Controls/Card.xaml.cs +++ b/Flow.Launcher/Resources/Controls/Card.xaml.cs @@ -12,10 +12,27 @@ namespace Flow.Launcher.Resources.Controls InsideFit } + public enum CardGroupPosition + { + NotInGroup, + First, + Middle, + Last + } + public Card() { InitializeComponent(); } + + public CardGroupPosition GroupPosition + { + get { return (CardGroupPosition)GetValue(GroupPositionProperty); } + set { SetValue(GroupPositionProperty, value); } + } + public static readonly DependencyProperty GroupPositionProperty = + DependencyProperty.Register(nameof(GroupPosition), typeof(CardGroupPosition), typeof(Card), new PropertyMetadata(CardGroupPosition.NotInGroup)); + public string Title { get { return (string)GetValue(TitleProperty); } diff --git a/Flow.Launcher/Resources/Controls/CardGroup.xaml b/Flow.Launcher/Resources/Controls/CardGroup.xaml new file mode 100644 index 000000000..d3383d20c --- /dev/null +++ b/Flow.Launcher/Resources/Controls/CardGroup.xaml @@ -0,0 +1,31 @@ + + + + + + + + + + + + diff --git a/Flow.Launcher/Resources/Controls/CardGroup.xaml.cs b/Flow.Launcher/Resources/Controls/CardGroup.xaml.cs new file mode 100644 index 000000000..6ddbf3597 --- /dev/null +++ b/Flow.Launcher/Resources/Controls/CardGroup.xaml.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.ObjectModel; +using System.Windows; +using System.Windows.Controls; + +namespace Flow.Launcher.Resources.Controls; + +public partial class CardGroup : UserControl +{ + public new ObservableCollection Content + { + get { return (ObservableCollection)GetValue(ContentProperty); } + set { SetValue(ContentProperty, value); } + } + + public static readonly DependencyProperty ContentProperty = + DependencyProperty.Register(nameof(Content), typeof(ObservableCollection), typeof(CardGroup)); + + public CardGroup() + { + InitializeComponent(); + DataContext = this; + Content = new ObservableCollection(); + } +} diff --git a/Flow.Launcher/Resources/Controls/CardGroupCardStyleSelector.cs b/Flow.Launcher/Resources/Controls/CardGroupCardStyleSelector.cs new file mode 100644 index 000000000..605934e80 --- /dev/null +++ b/Flow.Launcher/Resources/Controls/CardGroupCardStyleSelector.cs @@ -0,0 +1,21 @@ +using System.Windows; +using System.Windows.Controls; + +namespace Flow.Launcher.Resources.Controls; + +public class CardGroupCardStyleSelector : StyleSelector +{ + public Style FirstStyle { get; set; } + public Style MiddleStyle { get; set; } + public Style LastStyle { get; set; } + + public override Style SelectStyle(object item, DependencyObject container) + { + var itemsControl = ItemsControl.ItemsControlFromItemContainer(container); + var index = itemsControl.ItemContainerGenerator.IndexFromContainer(container); + + if (index == 0) return FirstStyle; + if (index == itemsControl.Items.Count - 1) return LastStyle; + return MiddleStyle; + } +} From 420446da7cc61283e1d3234b3a079456435243fd Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Tue, 30 Apr 2024 22:54:46 +0800 Subject: [PATCH 1289/2008] Update expect.txt --- .github/actions/spelling/expect.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index c4b1ee849..8a048c711 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -74,6 +74,7 @@ WCA_ACCENT_POLICY HGlobal dopusrt firefox +Firefox msedge svgc ime From 507a126076c257df30bade5799f7251428aab27b Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Wed, 1 May 2024 11:11:01 +0800 Subject: [PATCH 1290/2008] Try to add terms in allow.txt --- .github/actions/spelling/allow.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/actions/spelling/allow.txt b/.github/actions/spelling/allow.txt index 00cc67ea0..a36a6af3e 100644 --- a/.github/actions/spelling/allow.txt +++ b/.github/actions/spelling/allow.txt @@ -3,3 +3,6 @@ https ssh ubuntu runcount +Firefox +Português +Português (Brasil) From a337163d9e6748b4067e5611ca8f5f050c930dc0 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Wed, 1 May 2024 11:29:43 +0800 Subject: [PATCH 1291/2008] fix typo --- Flow.Launcher.Plugin/Result.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 2d3757ddc..87b9a8b18 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -276,7 +276,7 @@ namespace Flow.Launcher.Plugin public string ProgressBarColor { get; set; } = "#26a0da"; /// - /// Contains data used to populate the the preview section of this result. + /// Contains data used to populate the preview section of this result. /// public PreviewInfo Preview { get; set; } = PreviewInfo.Default; From fb6b1bb5187d01035a95098147619f8bdb53f871 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Wed, 1 May 2024 14:19:20 +0600 Subject: [PATCH 1292/2008] Fix CardGroup overwriting DataContext of its children --- Flow.Launcher/Resources/Controls/CardGroup.xaml | 3 ++- Flow.Launcher/Resources/Controls/CardGroup.xaml.cs | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/CardGroup.xaml b/Flow.Launcher/Resources/Controls/CardGroup.xaml index d3383d20c..5ea9d1e60 100644 --- a/Flow.Launcher/Resources/Controls/CardGroup.xaml +++ b/Flow.Launcher/Resources/Controls/CardGroup.xaml @@ -26,6 +26,7 @@ - + diff --git a/Flow.Launcher/Resources/Controls/CardGroup.xaml.cs b/Flow.Launcher/Resources/Controls/CardGroup.xaml.cs index 6ddbf3597..02f4ca013 100644 --- a/Flow.Launcher/Resources/Controls/CardGroup.xaml.cs +++ b/Flow.Launcher/Resources/Controls/CardGroup.xaml.cs @@ -13,13 +13,12 @@ public partial class CardGroup : UserControl set { SetValue(ContentProperty, value); } } - public static readonly DependencyProperty ContentProperty = + public static new readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(ObservableCollection), typeof(CardGroup)); public CardGroup() { InitializeComponent(); - DataContext = this; Content = new ObservableCollection(); } } From bd867db99aa041b7699e0450287327d0944685f3 Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 2 May 2024 07:24:33 +0900 Subject: [PATCH 1293/2008] Add WMP warning --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/SettingWindow.xaml | 34 +++++++++++++++++++++++++++++ Flow.Launcher/SettingWindow.xaml.cs | 14 ++++++++++-- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index bda86e481..7aca36e22 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -158,6 +158,7 @@ Play a small sound when the search window opens Sound Effect Volume Adjust the volume of the sound effect + Flow Launcher can't play sound because "Windows Media Player" doesn't exist on your system. If you need sound, install WMP. Animation Use Animation in UI Animation Speed diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 84b91e312..fd999585d 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -2561,6 +2561,40 @@ + + + + + + + + + + diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index 8144c8ff8..58ffbb149 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -24,6 +24,7 @@ using KeyEventArgs = System.Windows.Input.KeyEventArgs; using MessageBox = System.Windows.MessageBox; using TextBox = System.Windows.Controls.TextBox; using ThemeManager = ModernWpf.ThemeManager; +using System.Diagnostics; namespace Flow.Launcher { @@ -63,9 +64,18 @@ namespace Flow.Launcher viewModel.PropertyChanged += new PropertyChangedEventHandler(SettingsWindowViewModelChanged); + CheckMediaPlayer(); InitializePosition(); } + private void CheckMediaPlayer() + { + + if (!File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Windows Media Player", "wmplayer.exe"))) + { + /* Binding WMPWarning visibility */ + } + } private void SettingsWindowViewModelChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(viewModel.ExternalPlugins)) @@ -294,8 +304,8 @@ namespace Flow.Launcher } private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */ - { - if (Keyboard.FocusedElement is not TextBox textBox) + { + if (Keyboard.FocusedElement is not TextBox textBox) { return; } From aaef48cd16cba97278b08168295e7d888ad627ac Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Thu, 2 May 2024 20:48:24 +0600 Subject: [PATCH 1294/2008] Replace Card.GroupPosition with CardGroup.Position attached property --- Flow.Launcher/Resources/Controls/Card.xaml | 6 ++--- Flow.Launcher/Resources/Controls/Card.xaml.cs | 16 ------------- .../Resources/Controls/CardGroup.xaml | 6 ++--- .../Resources/Controls/CardGroup.xaml.cs | 23 +++++++++++++++++++ 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/Card.xaml b/Flow.Launcher/Resources/Controls/Card.xaml index 147c0e650..c29a5f602 100644 --- a/Flow.Launcher/Resources/Controls/Card.xaml +++ b/Flow.Launcher/Resources/Controls/Card.xaml @@ -38,21 +38,21 @@ - + - + - + diff --git a/Flow.Launcher/Resources/Controls/Card.xaml.cs b/Flow.Launcher/Resources/Controls/Card.xaml.cs index db4a136a3..c8f788aca 100644 --- a/Flow.Launcher/Resources/Controls/Card.xaml.cs +++ b/Flow.Launcher/Resources/Controls/Card.xaml.cs @@ -12,27 +12,11 @@ namespace Flow.Launcher.Resources.Controls InsideFit } - public enum CardGroupPosition - { - NotInGroup, - First, - Middle, - Last - } - public Card() { InitializeComponent(); } - public CardGroupPosition GroupPosition - { - get { return (CardGroupPosition)GetValue(GroupPositionProperty); } - set { SetValue(GroupPositionProperty, value); } - } - public static readonly DependencyProperty GroupPositionProperty = - DependencyProperty.Register(nameof(GroupPosition), typeof(CardGroupPosition), typeof(Card), new PropertyMetadata(CardGroupPosition.NotInGroup)); - public string Title { get { return (string)GetValue(TitleProperty); } diff --git a/Flow.Launcher/Resources/Controls/CardGroup.xaml b/Flow.Launcher/Resources/Controls/CardGroup.xaml index 5ea9d1e60..f48bf4b6c 100644 --- a/Flow.Launcher/Resources/Controls/CardGroup.xaml +++ b/Flow.Launcher/Resources/Controls/CardGroup.xaml @@ -9,13 +9,13 @@ d:DesignHeight="300" d:DesignWidth="300"> Content { get { return (ObservableCollection)GetValue(ContentProperty); } @@ -16,6 +24,21 @@ public partial class CardGroup : UserControl public static new readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(ObservableCollection), typeof(CardGroup)); + public static readonly DependencyProperty PositionProperty = DependencyProperty.RegisterAttached( + "Position", typeof(CardGroupPosition), typeof(CardGroup), + new FrameworkPropertyMetadata(CardGroupPosition.NotInGroup, FrameworkPropertyMetadataOptions.AffectsRender) + ); + + public static void SetPosition(UIElement element, CardGroupPosition value) + { + element.SetValue(PositionProperty, value); + } + + public static CardGroupPosition GetPosition(UIElement element) + { + return (CardGroupPosition)element.GetValue(PositionProperty); + } + public CardGroup() { InitializeComponent(); From abe187a15e16dc36ce10df7c95ee0cca51316360 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 3 May 2024 00:38:46 +0800 Subject: [PATCH 1295/2008] Use keyboard keys markup --- README.md | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 9ebbe246c..a19d99987 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,10 @@ Dedicated to making your work flow more seamless. Search everything from applica -- Use the F1 key to open/hide the preview panel. +- Use F1 to toggle the preview panel. - Media files will be displayed as large images, otherwise a large icon and entire path will be displayed. - Turn on preview permanently via Settings (Always Preview). -- Use hotkeys (Ctrl+Plus,Minus / Ctrl+],[) to adjust flow's search window width and height quickly if the preview area is too narrow. -- This feature is currently in its early stages. +- Use hotkeys (Ctrl++/- and Ctrl+[/]) to adjust flow's search window width and height quickly if the preview area is too narrow. ### Everything Plugin Merged Into Explorer @@ -52,7 +51,7 @@ Dedicated to making your work flow more seamless. Search everything from applica - Drag an item to Discord or computer location. -- The target program determines whether the drop is to copy or move the item (can change via CTRL or Alt), and the operation is displayed on the mouse cursor. +- The target program determines whether the drop is to copy or move the item (can change via Ctrl or Alt), and the operation is displayed on the mouse cursor. ### Custom Shortcut @@ -156,7 +155,7 @@ And you can download [early access version](https://github.com/Flow-Launcher/Pre - Run batch and PowerShell commands as Administrator or a different user. -- Ctrl+Enter to Run as Administrator. +- Ctrl+Shift+Enter to Run as Administrator. ### Explorer @@ -206,7 +205,7 @@ And you can download [early access version](https://github.com/Flow-Launcher/Pre - Pause hotkey activation when you are playing games. -- When in search window use Ctrl+F12 to toggle on/off. +- When in search window use Ctrl+F12 to toggle on/off. - Type `Toggle Game Mode` @@ -271,22 +270,22 @@ And you can download [early access version](https://github.com/Flow-Launcher/Pre | ------------------------------------------------------------------ | ---------------------------------------------- | | Alt+ Space | Open search window (default and configurable) | | Enter | Execute | -| Ctrl+Shift+Enter | Run as admin | +| Ctrl+Shift+Enter | Run as admin | | | Scroll up & down | | | Back to result / Open Context Menu | -| Ctrl +O , Shift +Enter | Open Context Menu | +| Ctrl +O , Shift +Enter | Open Context Menu | | Tab | Autocomplete | | F1 | Toggle Preview Panel (default and configurable)| | Esc | Back to results / hide search window | -| Ctrl +C | Copy the actual folder / file | -| Ctrl +I | Open flow's settings | -| Ctrl +R | Run the current query again (refresh results) | +| Ctrl +C | Copy the actual folder / file | +| Ctrl +I | Open flow's settings | +| Ctrl +R | Run the current query again (refresh results) | | F5 | Reload all plugin data | -| Ctrl + F12 | Toggle Game Mode when in search window | -| Ctrl + +,- | Quickly change maximum results shown | -| Ctrl + [,] | Quickly change search window width | -| Ctrl + H | Open search history | -| Ctrl + Backspace | Back to previous directory | +| Ctrl + F12 | Toggle Game Mode when in search window | +| Ctrl + +,- | Quickly change maximum results shown | +| Ctrl + [,] | Quickly change search window width | +| Ctrl + H | Open search history | +| Ctrl + Backspace | Back to previous directory | ## System Command List From 5678790ce565c57ca94dd9cd58036ae8c57b5333 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 3 May 2024 00:44:31 +0800 Subject: [PATCH 1296/2008] Remove outdated info --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index a19d99987..128ae46bd 100644 --- a/README.md +++ b/README.md @@ -66,10 +66,6 @@ Dedicated to making your work flow more seamless. Search everything from applica - Support for .url files, flow can now search installed steam/epic games. - Improved UWP indexing. -### Improved Memory Usage - -- Fixed a memory leak and reduced overall memory usage. - ### Improved Plugin / Plugin Store - Search plugins in the Plugin Store and existing plugin tab. From c500e396495843954fa8195fbc1fac0cca96400c Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 3 May 2024 00:56:23 +0800 Subject: [PATCH 1297/2008] Refactor installation guide --- README.md | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 128ae46bd..b2b8c5a75 100644 --- a/README.md +++ b/README.md @@ -99,11 +99,25 @@ Dedicated to making your work flow more seamless. Search everything from applica ### Installation -| [Windows 7+ installer](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest/download/Flow-Launcher-Setup.exe) | [Portable](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest/download/Flow-Launcher-Portable.zip) | -| :----------------------------------------------------------: | :----------------------------------------------------------: | +[Windows 7+ Installer](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest/download/Flow-Launcher-Setup.exe) or [Portable Version](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest/download/Flow-Launcher-Portable.zip) -| `winget install "Flow Launcher"` | `scoop install Flow-Launcher` | `choco install Flow-Launcher` | -| :------------------------------: | :------------------------------: | :------------------------------: | + +#### Winget + +``` +winget install "Flow Launcher" +``` +#### Scoop + +``` +scoop install Flow-Launcher +``` + +#### Chocolatey + +``` +choco install Flow-Launcher +``` > When installing for the first time Windows may raise an issue about security due to code not being signed, if you downloaded from this repo then you are good to continue the set up. From c1ffd1ca8fddd5065ebfaeb6bca5ac0cf94f9f8b Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 3 May 2024 01:09:04 +0800 Subject: [PATCH 1298/2008] Add language list --- README.md | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b2b8c5a75..3c1d2c4f3 100644 --- a/README.md +++ b/README.md @@ -196,12 +196,40 @@ And you can download [early access version](https://github.com/Flow-Launcher/Pre - There are various themes and you also can make your own. -### 💬 Language +### 💬 Languages - Supports languages from Chinese to Italian and more. -- Supports Pinyin search. +- Supports Pinyin (拼音) search. - [Crowdin](https://crowdin.com/project/flow-launcher) support for language translations. + +Supported languages +- English +- 中文 +- 中文(繁体) +- Українська +- Русский +- Français +- 日本語 +- Dutch +- Polski +- Dansk +- de, Deutsch +- ko, 한국어 +- Srpski +- Português +- Português (Brasil) +- Spanish +- es-419, Spanish (Latin America) +- Italiano +- Norsk Bokmål +- Slovenčina +- Türkçe +- čeština +- اللغة العربية +- Tiếng Việt + + ### Portable - Fully portable. From 79eaef533d549a0f3cfe4ff00529cc9a3ced9d5d Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 3 May 2024 01:13:28 +0800 Subject: [PATCH 1299/2008] Update wording & add description --- README.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3c1d2c4f3..f33bd00a3 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,10 @@

-Dedicated to making your work flow more seamless. Search everything from applications, files, bookmarks, YouTube, Twitter and more. Flow will continue to evolve, designed to be open and built with the community at heart. +A open source launcher app.

+ +

+Dedicated to making your work flow more seamless. Search everything from applications, files, bookmarks, YouTube, Twitter and more. Flow will continue to evolve, designed to be open and built with the community at heart.

Remember to star it, flow will love you more :)

@@ -31,7 +34,7 @@ Dedicated to making your work flow more seamless. Search everything from applica - Use F1 to toggle the preview panel. - Media files will be displayed as large images, otherwise a large icon and entire path will be displayed. - Turn on preview permanently via Settings (Always Preview). -- Use hotkeys (Ctrl++/- and Ctrl+[/]) to adjust flow's search window width and height quickly if the preview area is too narrow. +- Use Ctrl++/- and Ctrl+[/] to adjust search window width and height quickly if the preview area is too narrow. ### Everything Plugin Merged Into Explorer @@ -44,14 +47,14 @@ Dedicated to making your work flow more seamless. Search everything from applica -- Display the date and time when the search window is triggered. +- Display date and time in search window. ### Drag & Drop -- Drag an item to Discord or computer location. -- The target program determines whether the drop is to copy or move the item (can change via Ctrl or Alt), and the operation is displayed on the mouse cursor. +- Drag a file/folder to File Exlporer, or even Discord. +- Copy/move behavior can be change via Ctrl or Shift, and the operation is displayed on the mouse cursor. ### Custom Shortcut @@ -62,11 +65,11 @@ Dedicated to making your work flow more seamless. Search everything from applica ### Improved Program Plugin -- PATH is now indexed +- PATH is now indexed. - Support for .url files, flow can now search installed steam/epic games. - Improved UWP indexing. -### Improved Plugin / Plugin Store +### Improved Plugin Store - Search plugins in the Plugin Store and existing plugin tab. - Categorised sections in Plugin Store to easily see new and updated plugins. @@ -78,7 +81,7 @@ Dedicated to making your work flow more seamless. Search everything from applica - The design has been adjusted to align to the overall look and feel of flow. - Simplified the information displayed on buttons -🚂[Full Changelogs](https://github.com/Flow-Launcher/Flow.Launcher/releases) +🚂[Full Changelog](https://github.com/Flow-Launcher/Flow.Launcher/releases) @@ -243,7 +246,7 @@ And you can download [early access version](https://github.com/Flow-Launcher/Pre - Pause hotkey activation when you are playing games. -- When in search window use Ctrl+F12 to toggle on/off. +- When in search window use Ctrl+F12 to toggle on/off. - Type `Toggle Game Mode` From 48384a8beaa0cc159b468d9e6821cc87a6a441de Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 3 May 2024 01:17:18 +0800 Subject: [PATCH 1300/2008] collapsed language list --- README.md | 54 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index f33bd00a3..8b16a3035 100644 --- a/README.md +++ b/README.md @@ -205,33 +205,35 @@ And you can download [early access version](https://github.com/Flow-Launcher/Pre - Supports Pinyin (拼音) search. - [Crowdin](https://crowdin.com/project/flow-launcher) support for language translations. - +
Supported languages -- English -- 中文 -- 中文(繁体) -- Українська -- Русский -- Français -- 日本語 -- Dutch -- Polski -- Dansk -- de, Deutsch -- ko, 한국어 -- Srpski -- Português -- Português (Brasil) -- Spanish -- es-419, Spanish (Latin America) -- Italiano -- Norsk Bokmål -- Slovenčina -- Türkçe -- čeština -- اللغة العربية -- Tiếng Việt - +
    +
  • English
  • +
  • 中文
  • +
  • 中文(繁体)
  • +
  • Українська
  • +
  • Русский
  • +
  • Français
  • +
  • 日本語
  • +
  • Dutch
  • +
  • Polski
  • +
  • Dansk
  • +
  • de, Deutsch
  • +
  • ko, 한국어
  • +
  • Srpski
  • +
  • Português
  • +
  • Português (Brasil)
  • +
  • Spanish
  • +
  • es-419, Spanish (Latin America)
  • +
  • Italiano
  • +
  • Norsk Bokmål
  • +
  • Slovenčina
  • +
  • Türkçe
  • +
  • čeština
  • +
  • اللغة العربية
  • +
  • Tiếng Việt
  • +
+
### Portable From 28c261238b9245660e8010e2a600f31504a8c50f Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 3 May 2024 01:22:52 +0800 Subject: [PATCH 1301/2008] Fix double key --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8b16a3035..55b6a369a 100644 --- a/README.md +++ b/README.md @@ -313,22 +313,22 @@ And you can download [early access version](https://github.com/Flow-Launcher/Pre | ------------------------------------------------------------------ | ---------------------------------------------- | | Alt+ Space | Open search window (default and configurable) | | Enter | Execute | -| Ctrl+Shift+Enter | Run as admin | +| Ctrl+Shift+Enter | Run as admin | | | Scroll up & down | | | Back to result / Open Context Menu | -| Ctrl +O , Shift +Enter | Open Context Menu | +| Ctrl +O , Shift +Enter | Open Context Menu | | Tab | Autocomplete | | F1 | Toggle Preview Panel (default and configurable)| | Esc | Back to results / hide search window | -| Ctrl +C | Copy the actual folder / file | -| Ctrl +I | Open flow's settings | -| Ctrl +R | Run the current query again (refresh results) | +| Ctrl +C | Copy the actual folder / file | +| Ctrl +I | Open flow's settings | +| Ctrl +R | Run the current query again (refresh results) | | F5 | Reload all plugin data | -| Ctrl + F12 | Toggle Game Mode when in search window | -| Ctrl + +,- | Quickly change maximum results shown | -| Ctrl + [,] | Quickly change search window width | -| Ctrl + H | Open search history | -| Ctrl + Backspace | Back to previous directory | +| Ctrl + F12 | Toggle Game Mode when in search window | +| Ctrl + +,- | Quickly change maximum results shown | +| Ctrl + [,] | Quickly change search window width | +| Ctrl + H | Open search history | +| Ctrl + Backspace | Back to previous directory | ## System Command List From a4f7a47fbb8dff0cec8a7db8ea5bfcffd991277e Mon Sep 17 00:00:00 2001 From: DB P Date: Fri, 3 May 2024 06:53:14 +0900 Subject: [PATCH 1302/2008] Update Flow.Launcher/Languages/en.xaml Co-authored-by: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> --- Flow.Launcher/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 7aca36e22..9962646c6 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -158,7 +158,7 @@ Play a small sound when the search window opens Sound Effect Volume Adjust the volume of the sound effect - Flow Launcher can't play sound because "Windows Media Player" doesn't exist on your system. If you need sound, install WMP. + Sound effect is unavailable because Windows Media Player is missing. Please install it if you need sound effect. Animation Use Animation in UI Animation Speed From 336e9726829a0df0246c65e80b01869f2d1d59f0 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Fri, 3 May 2024 05:05:41 +0600 Subject: [PATCH 1303/2008] Fully functional Hotkey pane in the settings window --- Flow.Launcher/CustomShortcutSetting.xaml.cs | 2 +- .../SettingsPaneGeneralViewModel.cs | 10 +- .../ViewModels/SettingsPaneHotkeyViewModel.cs | 134 +++ .../Views/SettingsPaneHotkey.xaml | 841 +++++++++--------- .../Views/SettingsPaneHotkey.xaml.cs | 31 +- .../SettingPages/Views/SettingsPaneTheme.xaml | 8 + 6 files changed, 558 insertions(+), 468 deletions(-) create mode 100644 Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs diff --git a/Flow.Launcher/CustomShortcutSetting.xaml.cs b/Flow.Launcher/CustomShortcutSetting.xaml.cs index 097d6a53b..880c49787 100644 --- a/Flow.Launcher/CustomShortcutSetting.xaml.cs +++ b/Flow.Launcher/CustomShortcutSetting.xaml.cs @@ -47,7 +47,7 @@ namespace Flow.Launcher } // Check if key is modified or adding a new one if (((update && originalKey != Key) || !update) - && viewModel.ShortcutExists(Key)) + && (viewModel?.ShortcutExists(Key) ?? false)) // TODO Remove this check after removing unused code from SettingWindow.xaml.cs { MessageBox.Show(InternationalizationManager.Instance.GetTranslation("duplicateShortcut")); return; diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index e405ccc96..a9718a0ac 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -7,7 +7,6 @@ using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; @@ -16,7 +15,7 @@ namespace Flow.Launcher.SettingPages.ViewModels; public partial class SettingsPaneGeneralViewModel : BaseModel { - public Settings Settings { get; set; } + public Settings Settings { get; } private readonly Updater _updater; private readonly IPortable _portable; @@ -150,13 +149,6 @@ public partial class SettingsPaneGeneralViewModel : BaseModel .Select(v => v.ToString()) .ToList(); - public List OpenResultModifiersList => new List - { - KeyConstant.Alt, - KeyConstant.Ctrl, - $"{KeyConstant.Ctrl}+{KeyConstant.Alt}" - }; - public List Languages => InternationalizationManager.Instance.LoadAvailableLanguages(); public IEnumerable MaxResultsRange => Enumerable.Range(2, 16); diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs new file mode 100644 index 000000000..f56c4a971 --- /dev/null +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs @@ -0,0 +1,134 @@ +using System.Windows; +using CommunityToolkit.Mvvm.Input; +using Flow.Launcher.Core.Resource; +using Flow.Launcher.Helper; +using Flow.Launcher.Infrastructure; +using Flow.Launcher.Infrastructure.Hotkey; +using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; + +namespace Flow.Launcher.SettingPages.ViewModels; + +public partial class SettingsPaneHotkeyViewModel : BaseModel +{ + public Settings Settings { get; } + + public CustomPluginHotkey SelectedCustomPluginHotkey { get; set; } + public CustomShortcutModel SelectedCustomShortcut { get; set; } + + public string[] OpenResultModifiersList => new[] + { + KeyConstant.Alt, + KeyConstant.Ctrl, + $"{KeyConstant.Ctrl}+{KeyConstant.Alt}" + }; + + public SettingsPaneHotkeyViewModel(Settings settings) + { + Settings = settings; + } + + [RelayCommand] + private void SetTogglingHotkey(HotkeyModel hotkey) + { + HotKeyMapper.SetHotkey(hotkey, HotKeyMapper.OnToggleHotkey); + } + + [RelayCommand] + private void CustomHotkeyDelete() + { + var item = SelectedCustomPluginHotkey; + if (item is null) + { + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + return; + } + + var result = MessageBox.Show( + string.Format( + InternationalizationManager.Instance.GetTranslation("deleteCustomHotkeyWarning"), item.Hotkey + ), + InternationalizationManager.Instance.GetTranslation("delete"), + MessageBoxButton.YesNo + ); + + if (result is MessageBoxResult.Yes) + { + Settings.CustomPluginHotkeys.Remove(item); + HotKeyMapper.RemoveHotkey(item.Hotkey); + } + } + + [RelayCommand] + private void CustomHotkeyEdit() + { + var item = SelectedCustomPluginHotkey; + if (item is null) + { + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + return; + } + + var window = new CustomQueryHotkeySetting(null, Settings); + window.UpdateItem(item); + window.ShowDialog(); + } + + [RelayCommand] + private void CustomHotkeyAdd() + { + new CustomQueryHotkeySetting(null, Settings).ShowDialog(); + } + + [RelayCommand] + private void CustomShortcutDelete() + { + var item = SelectedCustomShortcut; + if (item is null) + { + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + return; + } + + var result = MessageBox.Show( + string.Format( + InternationalizationManager.Instance.GetTranslation("deleteCustomShortcutWarning"), item.Key, item.Value + ), + InternationalizationManager.Instance.GetTranslation("delete"), + MessageBoxButton.YesNo + ); + + if (result is MessageBoxResult.Yes) + { + Settings.CustomShortcuts.Remove(item); + } + } + + [RelayCommand] + private void CustomShortcutEdit() + { + var item = SelectedCustomShortcut; + if (item is null) + { + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + return; + } + + var window = new CustomShortcutSetting(item.Key, item.Value, null); + if (window.ShowDialog() is not true) return; + + var index = Settings.CustomShortcuts.IndexOf(item); + Settings.CustomShortcuts[index] = new CustomShortcutModel(window.Key, window.Value); + } + + [RelayCommand] + private void CustomShortcutAdd() + { + var window = new CustomShortcutSetting(null); + if (window.ShowDialog() is true) + { + var shortcut = new CustomShortcutModel(window.Key, window.Value); + Settings.CustomShortcuts.Add(shortcut); + } + } +} diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml index 7afb7bdc7..170b596f0 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml @@ -1,472 +1,433 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + Title="{DynamicResource OpenContainFolderHotkey}" + Icon="" + Type="Inside"> + + + + + + + + + + + + + HotkeySettings="{Binding Settings}" + DefaultHotkey="Ctrl+I" + Hotkey="{Binding Settings.OpenContextMenuHotkey}" + ValidateKeyGesture="False" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + - + + + + + + +
+ + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + - - - - - - - - + HorizontalAlignment="Right" + VerticalAlignment="Top" + Orientation="Horizontal"> + + + + + + + + + + + + +  + + + - - - - - - - - - - - - - - - - -  - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index fe1ea4e7b..d85d50e6f 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -49,6 +49,9 @@ namespace Flow.Launcher.ViewModel case nameof(Settings.WindowSize): OnPropertyChanged(nameof(WindowWidthSize)); break; + case nameof(Settings.WindowHeightSize): + OnPropertyChanged(nameof(WindowHeightSize)); + break; case nameof(Settings.UseDate): case nameof(Settings.DateFormat): OnPropertyChanged(nameof(DateText)); @@ -450,6 +453,34 @@ namespace Flow.Launcher.ViewModel } } + public double WindowHeightSize + { + get => Settings.WindowHeightSize; + set => Settings.WindowHeightSize = value; + } + + public double ItemHeightSize + { + get => Settings.ItemHeightSize; + set => Settings.ItemHeightSize = value; + } + + public double queryBoxFontSize + { + get => Settings.QueryBoxFontSize; + set => Settings.QueryBoxFontSize = value; + } + public double resultItemFontSize + { + get => Settings.ResultItemFontSize; + set => Settings.ResultItemFontSize = value; + } + + public double resultSubItemFontSize + { + get => Settings.ResultSubItemFontSize; + set => Settings.ResultSubItemFontSize = value; + } public class ColorScheme { public string Display { get; set; } @@ -838,6 +869,51 @@ namespace Flow.Launcher.ViewModel } } + public FontFamily SelectedResultSubFont + { + get + { + if (Fonts.SystemFontFamilies.Count(o => + o.FamilyNames.Values != null && + o.FamilyNames.Values.Contains(Settings.ResultSubFont)) > 0) + { + var font = new FontFamily(Settings.ResultSubFont); + return font; + } + else + { + var font = new FontFamily("Segoe UI"); + return font; + } + } + set + { + Settings.ResultSubFont = value.ToString(); + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public FamilyTypeface SelectedResultSubFontFaces + { + get + { + var typeface = SyntaxSugars.CallOrRescueDefault( + () => SelectedResultSubFont.ConvertFromInvariantStringsOrNormal( + Settings.ResultSubFontStyle, + Settings.ResultSubFontWeight, + Settings.ResultSubFontStretch + )); + return typeface; + } + set + { + Settings.ResultSubFontStretch = value.Stretch.ToString(); + Settings.ResultSubFontWeight = value.Weight.ToString(); + Settings.ResultSubFontStyle = value.Style.ToString(); + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + public string ThemeImage => Constant.QueryTextBoxIconImagePath; #endregion From 3659399ddaccca09943d902453925e2b02407920 Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 14 May 2024 18:03:26 +0900 Subject: [PATCH 1317/2008] Remove Hand Cursor Style --- Flow.Launcher/ResultListBox.xaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml index 68d614e5b..382b7c2e4 100644 --- a/Flow.Launcher/ResultListBox.xaml +++ b/Flow.Launcher/ResultListBox.xaml @@ -48,7 +48,6 @@ Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" - Cursor="Hand" UseLayoutRounding="False"> @@ -210,7 +209,7 @@ - + From 5670085275c5bb936d6a824f109adb010d330e0d Mon Sep 17 00:00:00 2001 From: DB p Date: Wed, 15 May 2024 23:30:27 +0900 Subject: [PATCH 1318/2008] - add soundplay for no WMP - fix warning visibility --- Flow.Launcher/MainWindow.xaml.cs | 24 +++++++++++++++++++----- Flow.Launcher/SettingWindow.xaml | 2 +- Flow.Launcher/SettingWindow.xaml.cs | 2 +- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 76e587cdc..2678d7c27 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -29,6 +29,7 @@ using DataObject = System.Windows.DataObject; using System.Windows.Media; using System.Windows.Interop; using System.Runtime.InteropServices; +using System.IO; namespace Flow.Launcher { @@ -46,7 +47,8 @@ namespace Flow.Launcher private ContextMenu contextMenu = new ContextMenu(); private MainViewModel _viewModel; private bool _animating; - MediaPlayer animationSound = new MediaPlayer(); + MediaPlayer animationSoundWMP = new MediaPlayer(); + SoundPlayer animationSoundWPF = new SoundPlayer(AppDomain.CurrentDomain.BaseDirectory + "Resources\\open.wav"); #endregion @@ -59,7 +61,7 @@ namespace Flow.Launcher InitializeComponent(); InitializePosition(); - animationSound.Open(new Uri(AppDomain.CurrentDomain.BaseDirectory + "Resources\\open.wav")); + animationSoundWMP.Open(new Uri(AppDomain.CurrentDomain.BaseDirectory + "Resources\\open.wav")); DataObject.AddPastingHandler(QueryTextBox, OnPaste); } @@ -137,9 +139,7 @@ namespace Flow.Launcher { if (_settings.UseSound) { - animationSound.Position = TimeSpan.Zero; - animationSound.Volume = _settings.SoundVolume / 100.0; - animationSound.Play(); + SoundPlay(); } UpdatePosition(); PreviewReset(); @@ -503,6 +503,20 @@ namespace Flow.Launcher windowsb.Begin(FlowMainWindow); } + private void SoundPlay() + { + + if (!File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Windows Media Player", "wmplayer.exe"))) + { + animationSoundWPF.Play(); + } + else + { + animationSoundWMP.Position = TimeSpan.Zero; + animationSoundWMP.Volume = _settings.SoundVolume / 100.0; + animationSoundWMP.Play(); + } + } private void OnMouseDown(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left) DragMove(); diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index fd999585d..daacd76d5 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -2570,7 +2570,7 @@ BorderBrush="{DynamicResource Color03B}" BorderThickness="0,1,0,0" CornerRadius="0 0 5 5" - Visibility="Visible"> + Visibility="Collapsed"> diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index 58ffbb149..292559b2f 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -73,7 +73,7 @@ namespace Flow.Launcher if (!File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Windows Media Player", "wmplayer.exe"))) { - /* Binding WMPWarning visibility */ + WMPWarning.Visibility = Visibility.Visible; } } private void SettingsWindowViewModelChanged(object sender, PropertyChangedEventArgs e) From a64f10e3123949e71ff27881ec729b62233a3772 Mon Sep 17 00:00:00 2001 From: DB p Date: Wed, 15 May 2024 23:36:33 +0900 Subject: [PATCH 1319/2008] - Adjust Warning String --- Flow.Launcher/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 9962646c6..418efe1e2 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -158,7 +158,7 @@ Play a small sound when the search window opens Sound Effect Volume Adjust the volume of the sound effect - Sound effect is unavailable because Windows Media Player is missing. Please install it if you need sound effect. + Windows Media Player is unavailable and is required for volume adjust. Please check your WMP installation Animation Use Animation in UI Animation Speed From c950a689d5b29c92f51743c03ff27d4d5fab156c Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 16 May 2024 01:11:27 +0900 Subject: [PATCH 1320/2008] - Convert Garulf's Query Cycle feature - Add Reset CycleIndex when close window --- .../UserSettings/Settings.cs | 6 ++ Flow.Launcher/MainWindow.xaml | 8 +++ Flow.Launcher/SettingWindow.xaml | 20 ++++++ Flow.Launcher/ViewModel/MainViewModel.cs | 68 ++++++++++++++++++- 4 files changed, 101 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 7bb8fe200..3d4433493 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -31,6 +31,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings public string SelectPrevPageHotkey { get; set; } = $"PageDown"; public string OpenContextMenuHotkey { get; set; } = $"Ctrl+O"; public string SettingWindowHotkey { get; set; } = $"Ctrl+I"; + public string CycleHistoryUpHotkey { get; set; } = $"{KeyConstant.Alt} + Up"; + public string CycleHistoryDownHotkey { get; set; } = $"{KeyConstant.Alt} + Down"; public string Language { @@ -340,6 +342,10 @@ namespace Flow.Launcher.Infrastructure.UserSettings list.Add(new(SelectNextPageHotkey, "SelectNextPageHotkey", () => SelectNextPageHotkey = "")); if(!string.IsNullOrEmpty(SelectPrevPageHotkey)) list.Add(new(SelectPrevPageHotkey, "SelectPrevPageHotkey", () => SelectPrevPageHotkey = "")); + if (!string.IsNullOrEmpty(CycleHistoryUpHotkey)) + list.Add(new(CycleHistoryUpHotkey, "CycleHistoryUpHotkey", () => CycleHistoryUpHotkey = "")); + if (!string.IsNullOrEmpty(CycleHistoryDownHotkey)) + list.Add(new(CycleHistoryDownHotkey, "CycleHistoryDownHotkey", () => CycleHistoryDownHotkey = "")); foreach (var customPluginHotkey in CustomPluginHotkeys) { diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 2e6e973a7..da5ec63bf 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -197,6 +197,14 @@ Key="{Binding SelectPrevPageHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}" Command="{Binding SelectPrevPageCommand}" Modifiers="{Binding SelectPrevPageHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" /> + + diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 119268d6b..4a563bc45 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -2810,6 +2810,26 @@ Type="Inside"> + + + + + + _userSelectedRecordStorage; private readonly FlowLauncherJsonStorage _topMostRecordStorage; private readonly History _history; + private int lasthistoryindex = 1; private readonly UserSelectedRecord _userSelectedRecord; private readonly TopMostRecord _topMostRecord; @@ -83,6 +84,12 @@ namespace Flow.Launcher.ViewModel case nameof(Settings.AutoCompleteHotkey): OnPropertyChanged(nameof(AutoCompleteHotkey)); break; + case nameof(Settings.CycleHistoryUpHotkey): + OnPropertyChanged(nameof(CycleHistoryUpHotkey)); + break; + case nameof(Settings.CycleHistoryDownHotkey): + OnPropertyChanged(nameof(CycleHistoryDownHotkey)); + break; case nameof(Settings.AutoCompleteHotkey2): OnPropertyChanged(nameof(AutoCompleteHotkey2)); break; @@ -256,6 +263,49 @@ namespace Flow.Launcher.ViewModel } } + [RelayCommand] + public void ReverseHistory() + { + if (_history.Items.Count > 0) + { + ChangeQueryText(_history.Items[_history.Items.Count - lasthistoryindex].Query.ToString()); + if (lasthistoryindex < _history.Items.Count) + { + lasthistoryindex++; + } + } + } + + [RelayCommand] + public void ForwardHistory() + { + if (_history.Items.Count > 0) + { + ChangeQueryText(_history.Items[_history.Items.Count - lasthistoryindex].Query.ToString()); + if (lasthistoryindex > 1) + { + lasthistoryindex--; + } + } + } + + [RelayCommand] + public void ReverseHistoryOnEmptyQuery() + { + var results = SelectedResults; + if (_history.Items.Count > 0 + && _queryText == String.Empty + && !HistorySelected() + && !ContextMenuSelected()) + { + ReverseHistory(); + } + else + { + SelectedResults.SelectPrevResult(); + } + } + [RelayCommand] private void LoadContextMenu() { @@ -394,7 +444,20 @@ namespace Flow.Launcher.ViewModel [RelayCommand] private void SelectPrevItem() { - SelectedResults.SelectPrevResult(); + var results = SelectedResults; + if (_history.Items.Count > 0 + && _queryText == String.Empty + && !HistorySelected() + && !ContextMenuSelected()) + { + lasthistoryindex = 1; + ReverseHistory(); + } + else + { + SelectedResults.SelectPrevResult(); + } + } [RelayCommand] @@ -690,6 +753,8 @@ namespace Flow.Launcher.ViewModel public string SelectPrevPageHotkey => VerifyOrSetDefaultHotkey(Settings.SelectPrevPageHotkey, ""); public string OpenContextMenuHotkey => VerifyOrSetDefaultHotkey(Settings.OpenContextMenuHotkey, "Ctrl+O"); public string SettingWindowHotkey => VerifyOrSetDefaultHotkey(Settings.SettingWindowHotkey, "Ctrl+I"); + public string CycleHistoryUpHotkey => VerifyOrSetDefaultHotkey(Settings.CycleHistoryUpHotkey, "Alt+Up"); + public string CycleHistoryDownHotkey => VerifyOrSetDefaultHotkey(Settings.CycleHistoryDownHotkey, "Alt+Down"); public string Image => Constant.QueryTextBoxIconImagePath; @@ -1116,6 +1181,7 @@ namespace Flow.Launcher.ViewModel public async void Hide() { + lasthistoryindex = 1; // Trick for no delay MainWindowOpacity = 0; lastContextMenuResult = new Result(); From 572e889c3449d604c7ad833cd8409f4bfb9da8ce Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 16 May 2024 01:44:00 +0900 Subject: [PATCH 1321/2008] Delete unused code --- Flow.Launcher/ViewModel/MainViewModel.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index ac5b980e0..2e52f92c1 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -289,23 +289,6 @@ namespace Flow.Launcher.ViewModel } } - [RelayCommand] - public void ReverseHistoryOnEmptyQuery() - { - var results = SelectedResults; - if (_history.Items.Count > 0 - && _queryText == String.Empty - && !HistorySelected() - && !ContextMenuSelected()) - { - ReverseHistory(); - } - else - { - SelectedResults.SelectPrevResult(); - } - } - [RelayCommand] private void LoadContextMenu() { From 3bcb5da99c7117241694ad1b742b3a62c20b39d0 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Wed, 15 May 2024 22:56:58 +0600 Subject: [PATCH 1322/2008] Implement plugin store settings pane --- .../SettingsPanePluginStoreViewModel.cs | 37 ++++++++++ .../Views/SettingsPanePluginStore.xaml | 50 +++++++------ .../Views/SettingsPanePluginStore.xaml.cs | 70 ++++++++++++++----- .../ViewModel/PluginStoreItemViewModel.cs | 21 +++--- 4 files changed, 131 insertions(+), 47 deletions(-) create mode 100644 Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs new file mode 100644 index 000000000..e06931011 --- /dev/null +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.Input; +using Flow.Launcher.Core.ExternalPlugins; +using Flow.Launcher.Infrastructure; +using Flow.Launcher.Plugin; +using Flow.Launcher.ViewModel; + +namespace Flow.Launcher.SettingPages.ViewModels; + +public partial class SettingsPanePluginStoreViewModel : BaseModel +{ + public string FilterText { get; set; } = string.Empty; + + public IList ExternalPlugins => PluginsManifest.UserPlugins + .Select(p => new PluginStoreItemViewModel(p)) + .OrderByDescending(p => p.Category == PluginStoreItemViewModel.NewRelease) + .ThenByDescending(p => p.Category == PluginStoreItemViewModel.RecentlyUpdated) + .ThenByDescending(p => p.Category == PluginStoreItemViewModel.None) + .ThenByDescending(p => p.Category == PluginStoreItemViewModel.Installed) + .ToList(); + + [RelayCommand] + private async Task RefreshExternalPluginsAsync() + { + await PluginsManifest.UpdateManifestAsync(); + OnPropertyChanged(nameof(ExternalPlugins)); + } + + public bool SatisfiesFilter(PluginStoreItemViewModel plugin) + { + return string.IsNullOrEmpty(FilterText) || + StringMatcher.FuzzySearch(FilterText, plugin.Name).IsSearchPrecisionScoreMet() || + StringMatcher.FuzzySearch(FilterText, plugin.Description).IsSearchPrecisionScoreMet(); + } +} diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml index bed68e86a..3b13f2e5a 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml @@ -1,25 +1,27 @@ - - - - - - - - - + + + + + + + @@ -38,7 +40,7 @@ FontSize="30" Style="{StaticResource PageTitle}" Text="{DynamicResource pluginStore}" - TextAlignment="left" /> + TextAlignment="Left" /> + VirtualizingPanel.ScrollUnit="Pixel"> - + @@ -273,7 +274,9 @@ HorizontalAlignment="Stretch" VerticalAlignment="Center" Content="{DynamicResource installbtn}" - Visibility="{Binding LabelInstalled, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter='!'}" /> + Visibility="{Binding LabelInstalled, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter='!'}" + Command="{Binding ShowCommandQueryCommand}" + CommandParameter="install" /> + - - - - - - - - - - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -180,7 +393,7 @@ Margin="0" Padding="0" HorizontalAlignment="Stretch" - BorderThickness="1,0,1,1" + BorderThickness="1 0 1 1" CornerRadius="0 0 5 5" Style="{DynamicResource SettingGroupBox}"> - + @@ -326,7 +539,7 @@ SelectedItem="{Binding SelectedResultFont}" /> @@ -346,7 +559,7 @@ - + - + + @@ -478,15 +691,15 @@ From d31c9a01190043258bd0b05c17075a8e377f4b5a Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 25 May 2024 11:05:58 +0900 Subject: [PATCH 1389/2008] Adjust Toggle Style --- .../Resources/CustomControlTemplate.xaml | 262 ++++++-- .../SettingPages/Views/SettingsPaneTheme.xaml | 585 +++++++++--------- 2 files changed, 505 insertions(+), 342 deletions(-) diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index cbb828582..a53e61f8c 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -45,7 +45,7 @@ - + + @@ -867,7 +1029,7 @@ Grid.Row="1" Grid.Column="0" Margin="{TemplateBinding Padding}" - Padding="0,0,32,0" + Padding="0 0 32 0" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Foreground="{TemplateBinding ui:ControlHelper.PlaceholderForeground}" @@ -887,7 +1049,7 @@ Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" - Margin="0,0,0,0" + Margin="0 0 0 0" Padding="{DynamicResource ComboBoxEditableTextPadding}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" @@ -906,7 +1068,7 @@ Grid.Row="1" Grid.Column="1" Width="30" - Margin="0,1,1,1" + Margin="0 1 1 1" HorizontalAlignment="Right" Background="Transparent" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" @@ -917,7 +1079,7 @@ Grid.Row="1" Grid.Column="1" MinHeight="{DynamicResource ComboBoxMinHeight}" - Margin="0,0,10,0" + Margin="0 0 10 0" HorizontalAlignment="Right" VerticalAlignment="Center" Data="{StaticResource ChevronDown}" @@ -944,7 +1106,7 @@ - + @@ -1063,7 +1225,7 @@ - + @@ -1073,7 +1235,7 @@ - + @@ -1083,7 +1245,7 @@ - + @@ -1121,7 +1283,7 @@ x:Key="DataGridComboBoxStyle" BasedOn="{StaticResource DefaultComboBoxStyle}" TargetType="ComboBox"> - + @@ -1133,7 +1295,7 @@ x:Key="DataGridTextBlockComboBoxStyle" BasedOn="{StaticResource DefaultComboBoxStyle}" TargetType="ComboBox"> - + @@ -1362,7 +1524,7 @@ - + @@ -1394,7 +1556,7 @@ BasedOn="{StaticResource DefaultTextBoxStyle}" TargetType="TextBox"> - + @@ -1549,7 +1711,7 @@ x:Name="SwitchAreaGrid" Grid.RowSpan="3" Grid.ColumnSpan="3" - Margin="0,5" + Margin="0 5" HorizontalAlignment="Right" ui:FocusVisualHelper.IsTemplateFocusTarget="True" Background="{DynamicResource ToggleSwitchContainerBackground}" /> @@ -1902,7 +2064,7 @@ - + @@ -2673,7 +2835,7 @@ x:Name="UpSpinButton" Grid.Row="1" Grid.Column="1" - Margin="4,0,0,0" + Margin="4 0 0 0" ui:ControlHelper.CornerRadius="4" Content="{StaticResource ChevronUp}" FontSize="{TemplateBinding FontSize}" @@ -2807,7 +2969,7 @@ BorderThickness="{TemplateBinding BorderThickness}" /> @@ -2961,7 +3123,7 @@ - + @@ -3219,7 +3381,7 @@ SnapsToDevicePixels="True"> @@ -4099,7 +4261,7 @@ Grid.Column="1" Width="48" Height="16" - Margin="0,0,0,0" + Margin="0 0 0 0" HorizontalAlignment="Center" VerticalAlignment="Center"> - + - + @@ -4391,7 +4553,7 @@ @@ -4414,7 +4576,7 @@ x:Name="IconBox" Width="16" Height="16" - Margin="16,0,0,0" + Margin="16 0 0 0" HorizontalAlignment="Center" VerticalAlignment="Center"> @@ -4841,7 +5003,7 @@ + Margin="0 0 0 8"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - + BorderThickness="1" + Style="{StaticResource SettingSeparatorStyle}" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Date: Sat, 25 May 2024 11:19:40 +0900 Subject: [PATCH 1390/2008] Change Edit Button to Icon --- .../SettingPages/Views/SettingsPaneTheme.xaml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml index 1e0b032c9..14070cd2d 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml @@ -50,12 +50,18 @@ Orientation="Horizontal"> + ToolTip="Show details"> + + Date: Sat, 25 May 2024 11:49:29 +0800 Subject: [PATCH 1391/2008] Update wording --- Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index 52daf20fb..cd4a1dc84 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -31,8 +31,8 @@ Everything Setting Preview Panel Size - Creation date - Modification date + Date Created + Date Modified Display File Info Date and time format Sort Option: @@ -115,7 +115,8 @@ {0} free of {1} Open in Default File Manager - Use '>' to search in this directory, '*' to search for file extensions or '>*' to combine both searches. + Use '>' to search in this directory, '*' to search for file extensions or '>*' to combine both searches. + Failed to load Everything SDK From d7272d9deb14ca2fde8bee19d755996a6b2e88e9 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 25 May 2024 13:04:49 +0900 Subject: [PATCH 1392/2008] Fix Scroll for bottom margin in theme --- Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml index 14070cd2d..e8eb728b7 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml @@ -25,7 +25,7 @@ @@ -40,7 +40,7 @@ Visibility="Collapsed" /> - + Date: Sat, 25 May 2024 14:24:18 +0900 Subject: [PATCH 1393/2008] Add Strings --- Flow.Launcher/Languages/en.xaml | 8 +++++++- .../SettingPages/Views/SettingsPaneTheme.xaml | 17 ++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 633b84b19..07eccf238 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -142,8 +142,13 @@ Launch programs as admin or a different user ProcessKiller Terminate unwanted processes + Search Bar Height + Item Height Query Box Font - Result Item Font + Result Title Font + Result Subtitle Font + Reset + Customize Window Mode Opacity Theme {0} not exists, fallback to default theme @@ -170,6 +175,7 @@ Clock Date + Hotkey Hotkeys diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml index e8eb728b7..75853118f 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml @@ -56,7 +56,7 @@ HorizontalAlignment="Left" VerticalAlignment="Top" Style="{DynamicResource CustomToggleButtonStyle}" - ToolTip="Show details"> + ToolTip="{DynamicResource CustomizeToolTip}"> - Reset - + HorizontalAlignment="Center" + Content="{DynamicResource resetCustomize}" /> From 4acbb7aadd2171b4c6d51790c9bb6ee90e63c741 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 25 May 2024 14:28:37 +0900 Subject: [PATCH 1394/2008] Removed MaxResult/Width item in settings --- .../Views/SettingsPaneGeneral.xaml | 78 +++++++++---------- .../SettingPages/Views/SettingsPaneTheme.xaml | 25 ------ 2 files changed, 36 insertions(+), 67 deletions(-) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 95505165d..c2b23a295 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -4,11 +4,11 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:ext="clr-namespace:Flow.Launcher.Resources.MarkupExtensions" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:settingsViewModels="clr-namespace:Flow.Launcher.SettingPages.ViewModels" xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure" - xmlns:ext="clr-namespace:Flow.Launcher.Resources.MarkupExtensions" Title="General" d:DataContext="{d:DesignInstance settingsViewModels:SettingsPaneGeneralViewModel}" d:DesignHeight="450" @@ -46,58 +46,62 @@ - + + SelectedValue="{Binding Settings.SearchWindowScreen}" + SelectedValuePath="Value" /> + Visibility="{ext:VisibleWhen {Binding Settings.SearchWindowScreen}, + IsEqualTo={x:Static userSettings:SearchWindowScreens.Custom}}" /> + Icon="" + Visibility="{ext:CollapsedWhen {Binding Settings.SearchWindowScreen}, + IsEqualTo={x:Static userSettings:SearchWindowScreens.RememberLastLaunchLocation}}"> + SelectedValue="{Binding Settings.SearchWindowAlign}" + SelectedValuePath="Value" /> - - - + Orientation="Horizontal" + Visibility="{ext:VisibleWhen {Binding Settings.SearchWindowAlign}, + IsEqualTo={x:Static userSettings:SearchWindowAligns.Custom}}"> + + + @@ -133,8 +137,7 @@ - + - - - - + SelectedValue="{Binding Settings.LastQueryMode}" + SelectedValuePath="Value" /> @@ -223,8 +218,7 @@ Title="{DynamicResource ShouldUsePinyin}" Icon="" Sub="{DynamicResource ShouldUsePinyinToolTip}"> - + - - - - - - - - Date: Sat, 25 May 2024 14:36:20 +0900 Subject: [PATCH 1395/2008] Adjust Quick Resize Logic --- Flow.Launcher/MainWindow.xaml | 12 ++++++------ Flow.Launcher/ViewModel/MainViewModel.cs | 12 ++---------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 1180e966b..f80d927a5 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -269,7 +269,7 @@ @@ -328,7 +328,7 @@ x:Name="ProgressBar" Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}" Height="2" - Margin="12,0,12,0" + Margin="12 0 12 0" HorizontalAlignment="Center" VerticalAlignment="Bottom" StrokeThickness="2" @@ -444,7 +444,7 @@ Style="{DynamicResource PreviewBorderStyle}" Visibility="{Binding ShowDefaultPreview}"> @@ -460,7 +460,7 @@ x:Name="PreviewGlyphIcon" Grid.Row="0" Height="Auto" - Margin="0,16,0,0" + Margin="0 16 0 0" FontFamily="{Binding Glyph.FontFamily}" Style="{DynamicResource PreviewGlyph}" Text="{Binding Glyph.Glyph}" @@ -469,7 +469,7 @@ x:Name="PreviewImageIcon" Grid.Row="0" MaxHeight="320" - Margin="0,16,0,0" + Margin="0 16 0 0" HorizontalAlignment="Center" Source="{Binding PreviewImage}" StretchDirection="DownOnly" @@ -488,7 +488,7 @@ 1920 || Settings.WindowSize == 1920) - { - Settings.WindowSize = 1920; - } - else - { - Settings.WindowSize += 100; - Settings.WindowLeft -= 50; - } - + Settings.WindowSize += 100; + Settings.WindowLeft -= 50; OnPropertyChanged(); } From 058158ee3274560c0bb9fe5f29df4efad865c293 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Sat, 25 May 2024 00:36:54 -0500 Subject: [PATCH 1396/2008] try appending runtimeidentifier instead of removing unused runtimes --- ...low.Launcher.Plugin.BrowserBookmark.csproj | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 234afe28a..2431d2a05 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -11,6 +11,7 @@ true false false + win true en @@ -36,44 +37,6 @@ false - - - - - - - - PreserveNewest From fa2df93dd7b23aa3be56da3da358854984c969e9 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 25 May 2024 14:03:14 +0800 Subject: [PATCH 1397/2008] Fix calculator decimal separator bug --- Flow.Launcher.Core/Resource/Internationalization.cs | 9 +++------ Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs | 2 +- .../ViewModels/SettingsPaneThemeViewModel.cs | 6 ++---- Flow.Launcher/ViewModel/MainViewModel.cs | 5 ++--- Plugins/Flow.Launcher.Plugin.Calculator/Main.cs | 4 ++-- Plugins/Flow.Launcher.Plugin.Calculator/plugin.json | 2 +- 6 files changed, 11 insertions(+), 17 deletions(-) diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index acc693ed5..06eb868b8 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -96,13 +96,10 @@ namespace Flow.Launcher.Core.Resource { LoadLanguage(language); } - // Culture of this thread - // Use CreateSpecificCulture to preserve possible user-override settings in Windows + // Culture of main thread + // Use CreateSpecificCulture to preserve possible user-override settings in Windows, if Flow's language culture is the same as Windows's CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(language.LanguageCode); CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture; - // App domain - CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture(language.LanguageCode); - CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.DefaultThreadCurrentCulture; // Raise event after culture is set Settings.Language = language.LanguageCode; @@ -193,7 +190,7 @@ namespace Flow.Launcher.Core.Resource { p.Metadata.Name = pluginI18N.GetTranslatedPluginTitle(); p.Metadata.Description = pluginI18N.GetTranslatedPluginDescription(); - pluginI18N.OnCultureInfoChanged(CultureInfo.DefaultThreadCurrentCulture); + pluginI18N.OnCultureInfoChanged(CultureInfo.CurrentCulture); } catch (Exception e) { diff --git a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs index fabd01a24..ed94771f0 100644 --- a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs +++ b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs @@ -44,7 +44,7 @@ public class QuerySuggestionBoxConverter : IMultiValueConverter // Check if Text will be larger than our QueryTextBox Typeface typeface = new Typeface(queryTextBox.FontFamily, queryTextBox.FontStyle, queryTextBox.FontWeight, queryTextBox.FontStretch); // TODO: Obsolete warning? - var ft = new FormattedText(queryTextBox.Text, CultureInfo.DefaultThreadCurrentCulture, System.Windows.FlowDirection.LeftToRight, typeface, queryTextBox.FontSize, Brushes.Black); + var ft = new FormattedText(queryTextBox.Text, CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, typeface, queryTextBox.FontSize, Brushes.Black); var offset = queryTextBox.Padding.Right; diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index bcdd94e1c..87c5b6aa8 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -21,8 +21,6 @@ namespace Flow.Launcher.SettingPages.ViewModels; public partial class SettingsPaneThemeViewModel : BaseModel { - private CultureInfo Culture => CultureInfo.DefaultThreadCurrentCulture; - public Settings Settings { get; } public static string LinkHowToCreateTheme => @"https://flowlauncher.com/docs/#/how-to-create-a-theme"; @@ -136,9 +134,9 @@ public partial class SettingsPaneThemeViewModel : BaseModel set => Settings.DateFormat = value; } - public string ClockText => DateTime.Now.ToString(TimeFormat, Culture); + public string ClockText => DateTime.Now.ToString(TimeFormat, CultureInfo.CurrentCulture); - public string DateText => DateTime.Now.ToString(DateFormat, Culture); + public string DateText => DateTime.Now.ToString(DateFormat, CultureInfo.CurrentCulture); public double WindowWidthSize { diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 01dc67b98..13d9d3bdf 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -485,7 +485,6 @@ namespace Flow.Launcher.ViewModel public Settings Settings { get; } public string ClockText { get; private set; } public string DateText { get; private set; } - public CultureInfo Culture => CultureInfo.DefaultThreadCurrentCulture; private async Task RegisterClockAndDateUpdateAsync() { @@ -494,9 +493,9 @@ namespace Flow.Launcher.ViewModel while (await timer.WaitForNextTickAsync().ConfigureAwait(false)) { if (Settings.UseClock) - ClockText = DateTime.Now.ToString(Settings.TimeFormat, Culture); + ClockText = DateTime.Now.ToString(Settings.TimeFormat, CultureInfo.CurrentCulture); if (Settings.UseDate) - DateText = DateTime.Now.ToString(Settings.DateFormat, Culture); + DateText = DateTime.Now.ToString(Settings.DateFormat, CultureInfo.CurrentCulture); } } diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs index 338b5bcbe..ade684ca1 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs @@ -62,7 +62,7 @@ namespace Flow.Launcher.Plugin.Caculator switch (_settings.DecimalSeparator) { case DecimalSeparator.Comma: - case DecimalSeparator.UseSystemLocale when CultureInfo.DefaultThreadCurrentCulture.NumberFormat.NumberDecimalSeparator == ",": + case DecimalSeparator.UseSystemLocale when CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator == ",": expression = query.Search.Replace(",", "."); break; default: @@ -158,7 +158,7 @@ namespace Flow.Launcher.Plugin.Caculator private string GetDecimalSeparator() { - string systemDecimalSeperator = CultureInfo.DefaultThreadCurrentCulture.NumberFormat.NumberDecimalSeparator; + string systemDecimalSeperator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; switch (_settings.DecimalSeparator) { case DecimalSeparator.UseSystemLocale: return systemDecimalSeperator; diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json b/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json index a77475460..ac2ece7b5 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json @@ -4,7 +4,7 @@ "Name": "Calculator", "Description": "Provide mathematical calculations.(Try 5*3-2 in Flow Launcher)", "Author": "cxfksword", - "Version": "3.1.0", + "Version": "3.1.1", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Caculator.dll", From 27392a53c3618425d047edda1189117c1bf4cb0a Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 25 May 2024 14:28:26 +0800 Subject: [PATCH 1398/2008] Fix output path --- .../Flow.Launcher.Plugin.Calculator.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj index 415f852f4..178485a8f 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj @@ -18,7 +18,7 @@ true portable false - ..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.Caculator\ + ..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.Calculator\ DEBUG;TRACE prompt 4 @@ -28,7 +28,7 @@ pdbonly true - ..\..\Output\Release\Plugins\Flow.Launcher.Plugin.Caculator\ + ..\..\Output\Release\Plugins\Flow.Launcher.Plugin.Calculator\ TRACE prompt 4 From e4621a5c878071861aa84eaef749f707b930c260 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 25 May 2024 14:35:14 +0800 Subject: [PATCH 1399/2008] Fix calculator typo --- Plugins/Flow.Launcher.Plugin.Calculator/DecimalSeparator.cs | 2 +- .../Flow.Launcher.Plugin.Calculator.csproj | 4 ++-- Plugins/Flow.Launcher.Plugin.Calculator/Main.cs | 6 +++--- Plugins/Flow.Launcher.Plugin.Calculator/NumberTranslator.cs | 2 +- Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs | 2 +- .../ViewModels/SettingsViewModel.cs | 2 +- .../Views/CalculatorSettings.xaml | 6 +++--- .../Views/CalculatorSettings.xaml.cs | 4 ++-- Plugins/Flow.Launcher.Plugin.Calculator/plugin.json | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/DecimalSeparator.cs b/Plugins/Flow.Launcher.Plugin.Calculator/DecimalSeparator.cs index 27bdf94ee..81a68739b 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/DecimalSeparator.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/DecimalSeparator.cs @@ -1,7 +1,7 @@ using System.ComponentModel; using Flow.Launcher.Core.Resource; -namespace Flow.Launcher.Plugin.Caculator +namespace Flow.Launcher.Plugin.Calculator { [TypeConverter(typeof(LocalizationConverter))] public enum DecimalSeparator diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj index 178485a8f..69c03b877 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj @@ -5,8 +5,8 @@ net7.0-windows {59BD9891-3837-438A-958D-ADC7F91F6F7E} Properties - Flow.Launcher.Plugin.Caculator - Flow.Launcher.Plugin.Caculator + Flow.Launcher.Plugin.Calculator + Flow.Launcher.Plugin.Calculator true true false diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs index ade684ca1..5077e6061 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs @@ -6,10 +6,10 @@ using System.Text.RegularExpressions; using System.Windows; using System.Windows.Controls; using Mages.Core; -using Flow.Launcher.Plugin.Caculator.ViewModels; -using Flow.Launcher.Plugin.Caculator.Views; +using Flow.Launcher.Plugin.Calculator.ViewModels; +using Flow.Launcher.Plugin.Calculator.Views; -namespace Flow.Launcher.Plugin.Caculator +namespace Flow.Launcher.Plugin.Calculator { public class Main : IPlugin, IPluginI18n, ISettingProvider { diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/NumberTranslator.cs b/Plugins/Flow.Launcher.Plugin.Calculator/NumberTranslator.cs index ed4aed75b..4eacb9d34 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/NumberTranslator.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/NumberTranslator.cs @@ -2,7 +2,7 @@ using System.Text; using System.Text.RegularExpressions; -namespace Flow.Launcher.Plugin.Caculator +namespace Flow.Launcher.Plugin.Calculator { /// /// Tries to convert all numbers in a text from one culture format to another. diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs index 615514873..8354863b8 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs @@ -1,5 +1,5 @@  -namespace Flow.Launcher.Plugin.Caculator +namespace Flow.Launcher.Plugin.Calculator { public class Settings { diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Calculator/ViewModels/SettingsViewModel.cs index afe4d1c0c..09f745669 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/ViewModels/SettingsViewModel.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; -namespace Flow.Launcher.Plugin.Caculator.ViewModels +namespace Flow.Launcher.Plugin.Calculator.ViewModels { public class SettingsViewModel : BaseModel { diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml index 9fd4bb17c..d6237c6da 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml @@ -1,13 +1,13 @@ /// Interaction logic for CalculatorSettings.xaml diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json b/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json index ac2ece7b5..6abc41668 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json @@ -7,6 +7,6 @@ "Version": "3.1.1", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", - "ExecuteFileName": "Flow.Launcher.Plugin.Caculator.dll", + "ExecuteFileName": "Flow.Launcher.Plugin.Calculator.dll", "IcoPath": "Images\\calculator.png" } \ No newline at end of file From 7b106c5cefac61f75d20ac8f141022aeb58f3f99 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 25 May 2024 15:40:21 +0900 Subject: [PATCH 1400/2008] Fix Sidebar Color --- Flow.Launcher/Resources/Dark.xaml | 3 ++- Flow.Launcher/Resources/Light.xaml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Resources/Dark.xaml b/Flow.Launcher/Resources/Dark.xaml index 5f6934f30..a910108e8 100644 --- a/Flow.Launcher/Resources/Dark.xaml +++ b/Flow.Launcher/Resources/Dark.xaml @@ -1033,7 +1033,8 @@ - + + diff --git a/Flow.Launcher/Resources/Light.xaml b/Flow.Launcher/Resources/Light.xaml index 6e06b99af..906430343 100644 --- a/Flow.Launcher/Resources/Light.xaml +++ b/Flow.Launcher/Resources/Light.xaml @@ -1030,7 +1030,8 @@ - + + From f98798066573dd9d61cf8b619aad78a2411c4a45 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Sat, 25 May 2024 13:08:24 +0600 Subject: [PATCH 1401/2008] Revert "try appending runtimeidentifier instead of removing unused runtimes" This reverts commit 058158ee3274560c0bb9fe5f29df4efad865c293. --- ...low.Launcher.Plugin.BrowserBookmark.csproj | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 2431d2a05..234afe28a 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -11,7 +11,6 @@ true false false - win true en @@ -37,6 +36,44 @@ false + + + + + + + + PreserveNewest From cedf0c6c1ef6c03ca2feeb91d575d8aaaeffa764 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 25 May 2024 16:16:02 +0900 Subject: [PATCH 1402/2008] - Add Reset Button Function - Fix Conflict --- Flow.Launcher/MainWindow.xaml | 1 + .../ViewModels/SettingsPaneThemeViewModel.cs | 24 +++++++++++++++++++ .../SettingPages/Views/SettingsPaneTheme.xaml | 2 +- .../Views/SettingsPaneTheme.xaml.cs | 5 ++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index ade997e20..f0f6c981e 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -521,6 +521,7 @@ + diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index bc96a86ff..2d04c49c3 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -470,4 +470,28 @@ public partial class SettingsPaneThemeViewModel : BaseModel { Settings = settings; } + + public void ResetCustomize() + { + Settings.QueryBoxFont = "Segoe UI"; + Settings.QueryBoxFontStyle = "Normal"; + Settings.QueryBoxFontWeight = "Normal"; + Settings.QueryBoxFontStretch = "Normal"; + Settings.QueryBoxFontSize = 20; + + Settings.ResultFont = "Segoe UI"; + Settings.ResultFontStyle = "Normal"; + Settings.ResultFontWeight = "Normal"; + Settings.ResultFontStretch = "Normal"; + Settings.ResultItemFontSize = 18; + + Settings.ResultSubFont = "Segoe UI"; + Settings.ResultSubFontStyle = "Normal"; + Settings.ResultSubFontWeight = "Normal"; + Settings.ResultSubFontStretch = "Normal"; + Settings.ResultSubItemFontSize = 14; + + Settings.ItemHeightSize = 52; + Settings.WindowHeightSize = 42; + } } diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml index c8425f822..8792a0e0a 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml @@ -255,7 +255,7 @@ Width="140" Margin="8" HorizontalAlignment="Center" - Content="{DynamicResource resetCustomize}" /> + Content="{DynamicResource resetCustomize}" Click="Reset_Click" /> diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs index 93cf7ad18..6132c452d 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs @@ -28,4 +28,9 @@ public partial class SettingsPaneTheme : Page { _viewModel.UpdateColorScheme(); } + + private void Reset_Click(object sender, System.Windows.RoutedEventArgs e) + { + _viewModel.ResetCustomize(); + } } From 5a0f4ac459476c685fc84128a65c24840e479f27 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 25 May 2024 22:22:51 +0900 Subject: [PATCH 1403/2008] Adjust Default Value --- Flow.Launcher.Infrastructure/UserSettings/Settings.cs | 4 ++-- .../ViewModels/SettingsPaneThemeViewModel.cs | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 6a52b0a97..bf269ba12 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -58,9 +58,9 @@ namespace Flow.Launcher.Infrastructure.UserSettings public bool UseDropShadowEffect { get; set; } = false; /* Appearance Settings. It should be separated from the setting later.*/ - public double WindowHeightSize { get; set; } = 40; + public double WindowHeightSize { get; set; } = 42; public double ItemHeightSize { get; set; } = 58; - public double QueryBoxFontSize { get; set; } = 18; + public double QueryBoxFontSize { get; set; } = 20; public double ResultItemFontSize { get; set; } = 16; public double ResultSubItemFontSize { get; set; } = 13; public string QueryBoxFont { get; set; } = FontFamily.GenericSansSerif.Name; diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index 2d04c49c3..260f1ea1f 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; using System.Globalization; using System.IO; using System.Linq; -using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; using CommunityToolkit.Mvvm.Input; @@ -483,15 +484,15 @@ public partial class SettingsPaneThemeViewModel : BaseModel Settings.ResultFontStyle = "Normal"; Settings.ResultFontWeight = "Normal"; Settings.ResultFontStretch = "Normal"; - Settings.ResultItemFontSize = 18; + Settings.ResultItemFontSize = 16; Settings.ResultSubFont = "Segoe UI"; Settings.ResultSubFontStyle = "Normal"; Settings.ResultSubFontWeight = "Normal"; Settings.ResultSubFontStretch = "Normal"; - Settings.ResultSubItemFontSize = 14; + Settings.ResultSubItemFontSize = 13; - Settings.ItemHeightSize = 52; + Settings.ItemHeightSize = 58; Settings.WindowHeightSize = 42; } } From de94f3950f8d0c0805d58c7352ab9759345e3e43 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 25 May 2024 23:55:41 +0800 Subject: [PATCH 1404/2008] Fix window height reset issue --- Flow.Launcher/MainWindow.xaml.cs | 7 ++++--- .../SettingPages/ViewModels/SettingsPaneThemeViewModel.cs | 2 +- Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml | 7 ++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 53828c57f..c333b6b04 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -27,8 +27,6 @@ using DataObject = System.Windows.DataObject; using System.Windows.Media; using System.Windows.Interop; using System.Runtime.InteropServices; -using System.Diagnostics; -using System.Windows.Media.Media3D; namespace Flow.Launcher { @@ -108,10 +106,12 @@ namespace Flow.Launcher } return IntPtr.Zero; } + private void OnResizeBegin() { } + private void OnResizeEnd() { int shadowMargin = 0; @@ -131,7 +131,8 @@ namespace Flow.Launcher _settings.WindowSize = Width; FlowMainWindow.SizeToContent = SizeToContent.Height; } - private void OnCopy(object sender, ExecutedRoutedEventArgs e) + + private void OnCopy(object sender, ExecutedRoutedEventArgs e) { var result = _viewModel.Results.SelectedItem?.Result; if (QueryTextBox.SelectionLength == 0 && result != null) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index 260f1ea1f..c1becf4ba 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -493,6 +493,6 @@ public partial class SettingsPaneThemeViewModel : BaseModel Settings.ResultSubItemFontSize = 13; Settings.ItemHeightSize = 58; - Settings.WindowHeightSize = 42; + WindowHeightSize = 42; } } diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml index 8792a0e0a..1eb358a04 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml @@ -255,7 +255,8 @@ Width="140" Margin="8" HorizontalAlignment="Center" - Content="{DynamicResource resetCustomize}" Click="Reset_Click" /> + Click="Reset_Click" + Content="{DynamicResource resetCustomize}" /> @@ -286,8 +287,8 @@ Date: Sun, 26 May 2024 00:36:40 +0800 Subject: [PATCH 1405/2008] Fix binding problem --- .../ViewModels/SettingsPaneThemeViewModel.cs | 211 ++++++++++++++---- .../SettingPages/Views/SettingsPaneTheme.xaml | 16 +- 2 files changed, 181 insertions(+), 46 deletions(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index c1becf4ba..8290df79e 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -77,22 +77,6 @@ public partial class SettingsPaneThemeViewModel : BaseModel set => Settings.ItemHeightSize = value; } - public double queryBoxFontSize - { - get => Settings.QueryBoxFontSize; - set => Settings.QueryBoxFontSize = value; - } - public double resultItemFontSize - { - get => Settings.ResultItemFontSize; - set => Settings.ResultItemFontSize = value; - } - - public double resultSubItemFontSize - { - get => Settings.ResultSubItemFontSize; - set => Settings.ResultSubItemFontSize = value; - } public List Themes => ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension).ToList(); @@ -169,12 +153,6 @@ public partial class SettingsPaneThemeViewModel : BaseModel public string DateText => DateTime.Now.ToString(DateFormat, Culture); - public double WindowWidthSize - { - get => Settings.WindowSize; - set => Settings.WindowSize = value; - } - public bool UseGlyphIcons { get => Settings.UseGlyphIcons; @@ -210,6 +188,7 @@ public partial class SettingsPaneThemeViewModel : BaseModel return speeds; } } + public bool UseSound { get => Settings.UseSound; @@ -472,27 +451,183 @@ public partial class SettingsPaneThemeViewModel : BaseModel Settings = settings; } + public string QueryBoxFont + { + get => Settings.QueryBoxFont; + set + { + Settings.QueryBoxFont = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string QueryBoxFontStyle + { + get => Settings.QueryBoxFontStyle; + set + { + Settings.QueryBoxFontStyle = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string QueryBoxFontWeight + { + get => Settings.QueryBoxFontWeight; + set + { + Settings.QueryBoxFontWeight = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string QueryBoxFontStretch + { + get => Settings.QueryBoxFontStretch; + set + { + Settings.QueryBoxFontStretch = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public double QueryBoxFontSize + { + get => Settings.QueryBoxFontSize; + set + { + Settings.QueryBoxFontSize = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string ResultFont + { + get => Settings.ResultFont; + set + { + Settings.ResultFont = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string ResultFontStyle + { + get => Settings.ResultFontStyle; + set + { + Settings.ResultFontStyle = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string ResultFontWeight + { + get => Settings.ResultFontWeight; + set + { + Settings.ResultFontWeight = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string ResultFontStretch + { + get => Settings.ResultFontStretch; + set + { + Settings.ResultFontStretch = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public double ResultItemFontSize + { + get => Settings.ResultItemFontSize; + set + { + Settings.ResultItemFontSize = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string ResultSubFont + { + get => Settings.ResultSubFont; + set + { + Settings.ResultSubFont = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string ResultSubFontStyle + { + get => Settings.ResultSubFontStyle; + set + { + Settings.ResultSubFontStyle = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string ResultSubFontWeight + { + get => Settings.ResultSubFontWeight; + set + { + Settings.ResultSubFontWeight = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string ResultSubFontStretch + { + get => Settings.ResultSubFontStretch; + set + { + Settings.ResultSubFontStretch = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public double ResultSubItemFontSize + { + get => Settings.ResultSubItemFontSize; + set + { + Settings.ResultSubItemFontSize = value; + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public int CustomAnimationLength + { + get => Settings.CustomAnimationLength; + set => Settings.CustomAnimationLength = value; + } + public void ResetCustomize() { - Settings.QueryBoxFont = "Segoe UI"; - Settings.QueryBoxFontStyle = "Normal"; - Settings.QueryBoxFontWeight = "Normal"; - Settings.QueryBoxFontStretch = "Normal"; - Settings.QueryBoxFontSize = 20; + QueryBoxFont = "Segoe UI"; + QueryBoxFontStyle = "Normal"; + QueryBoxFontWeight = "Normal"; + QueryBoxFontStretch = "Normal"; + QueryBoxFontSize = 20; - Settings.ResultFont = "Segoe UI"; - Settings.ResultFontStyle = "Normal"; - Settings.ResultFontWeight = "Normal"; - Settings.ResultFontStretch = "Normal"; - Settings.ResultItemFontSize = 16; + ResultFont = "Segoe UI"; + ResultFontStyle = "Normal"; + ResultFontWeight = "Normal"; + ResultFontStretch = "Normal"; + ResultItemFontSize = 16; - Settings.ResultSubFont = "Segoe UI"; - Settings.ResultSubFontStyle = "Normal"; - Settings.ResultSubFontWeight = "Normal"; - Settings.ResultSubFontStretch = "Normal"; - Settings.ResultSubItemFontSize = 13; + ResultSubFont = "Segoe UI"; + ResultSubFontStyle = "Normal"; + ResultSubFontWeight = "Normal"; + ResultSubFontStretch = "Normal"; + ResultSubItemFontSize = 13; - Settings.ItemHeightSize = 58; + ItemHeightSize = 58; WindowHeightSize = 42; } } diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml index 1eb358a04..f9758389f 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml @@ -114,7 +114,7 @@ Maximum="{Binding ElementName=WindowHeightValue, Path=Value, UpdateSourceTrigger=PropertyChanged}" Minimum="10" TickFrequency="1" - Value="{Binding queryBoxFontSize, Mode=TwoWay}" /> + Value="{Binding QueryBoxFontSize, Mode=TwoWay}" /> + Value="{Binding ResultItemFontSize, Mode=TwoWay}" /> + Value="{Binding ResultSubItemFontSize, Mode=TwoWay}" /> + Visibility="{Binding UseClock, Converter={StaticResource BoolToVisibilityConverter}}" /> + Visibility="{Binding UseDate, Converter={StaticResource BoolToVisibilityConverter}}" /> From 9a4d5dc8d61fc64a1343c515eae812848b5699d7 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 26 May 2024 10:56:21 +0800 Subject: [PATCH 1406/2008] Remove Vietnamese resource file --- Flow.Launcher/Properties/Resources.vi-VN.resx | 127 ------------------ 1 file changed, 127 deletions(-) delete mode 100644 Flow.Launcher/Properties/Resources.vi-VN.resx diff --git a/Flow.Launcher/Properties/Resources.vi-VN.resx b/Flow.Launcher/Properties/Resources.vi-VN.resx deleted file mode 100644 index b5e00e8a2..000000000 --- a/Flow.Launcher/Properties/Resources.vi-VN.resx +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - ..\Resources\app.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Images\gamemode.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - \ No newline at end of file From 4fd05f59f1a4375d51347172d684e39a1cb52f8b Mon Sep 17 00:00:00 2001 From: DB p Date: Sun, 26 May 2024 18:29:02 +0900 Subject: [PATCH 1407/2008] - RollBack reset logic and Adjust naming --- .../ViewModels/SettingsPaneThemeViewModel.cs | 202 ++---------------- .../SettingPages/Views/SettingsPaneTheme.xaml | 6 + .../Views/SettingsPaneTheme.xaml.cs | 26 ++- 3 files changed, 53 insertions(+), 181 deletions(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index 8290df79e..6d1f86a1f 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -77,6 +77,22 @@ public partial class SettingsPaneThemeViewModel : BaseModel set => Settings.ItemHeightSize = value; } + public double QueryBoxFontSize + { + get => Settings.QueryBoxFontSize; + set => Settings.QueryBoxFontSize = value; + } + public double ResultItemFontSize + { + get => Settings.ResultItemFontSize; + set => Settings.ResultItemFontSize = value; + } + + public double ResultSubItemFontSize + { + get => Settings.ResultSubItemFontSize; + set => Settings.ResultSubItemFontSize = value; + } public List Themes => ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension).ToList(); @@ -153,6 +169,12 @@ public partial class SettingsPaneThemeViewModel : BaseModel public string DateText => DateTime.Now.ToString(DateFormat, Culture); + public double WindowWidthSize + { + get => Settings.WindowSize; + set => Settings.WindowSize = value; + } + public bool UseGlyphIcons { get => Settings.UseGlyphIcons; @@ -188,7 +210,6 @@ public partial class SettingsPaneThemeViewModel : BaseModel return speeds; } } - public bool UseSound { get => Settings.UseSound; @@ -451,183 +472,4 @@ public partial class SettingsPaneThemeViewModel : BaseModel Settings = settings; } - public string QueryBoxFont - { - get => Settings.QueryBoxFont; - set - { - Settings.QueryBoxFont = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string QueryBoxFontStyle - { - get => Settings.QueryBoxFontStyle; - set - { - Settings.QueryBoxFontStyle = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string QueryBoxFontWeight - { - get => Settings.QueryBoxFontWeight; - set - { - Settings.QueryBoxFontWeight = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string QueryBoxFontStretch - { - get => Settings.QueryBoxFontStretch; - set - { - Settings.QueryBoxFontStretch = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public double QueryBoxFontSize - { - get => Settings.QueryBoxFontSize; - set - { - Settings.QueryBoxFontSize = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string ResultFont - { - get => Settings.ResultFont; - set - { - Settings.ResultFont = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string ResultFontStyle - { - get => Settings.ResultFontStyle; - set - { - Settings.ResultFontStyle = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string ResultFontWeight - { - get => Settings.ResultFontWeight; - set - { - Settings.ResultFontWeight = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string ResultFontStretch - { - get => Settings.ResultFontStretch; - set - { - Settings.ResultFontStretch = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public double ResultItemFontSize - { - get => Settings.ResultItemFontSize; - set - { - Settings.ResultItemFontSize = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string ResultSubFont - { - get => Settings.ResultSubFont; - set - { - Settings.ResultSubFont = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string ResultSubFontStyle - { - get => Settings.ResultSubFontStyle; - set - { - Settings.ResultSubFontStyle = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string ResultSubFontWeight - { - get => Settings.ResultSubFontWeight; - set - { - Settings.ResultSubFontWeight = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public string ResultSubFontStretch - { - get => Settings.ResultSubFontStretch; - set - { - Settings.ResultSubFontStretch = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public double ResultSubItemFontSize - { - get => Settings.ResultSubItemFontSize; - set - { - Settings.ResultSubItemFontSize = value; - ThemeManager.Instance.ChangeTheme(Settings.Theme); - } - } - - public int CustomAnimationLength - { - get => Settings.CustomAnimationLength; - set => Settings.CustomAnimationLength = value; - } - - public void ResetCustomize() - { - QueryBoxFont = "Segoe UI"; - QueryBoxFontStyle = "Normal"; - QueryBoxFontWeight = "Normal"; - QueryBoxFontStretch = "Normal"; - QueryBoxFontSize = 20; - - ResultFont = "Segoe UI"; - ResultFontStyle = "Normal"; - ResultFontWeight = "Normal"; - ResultFontStretch = "Normal"; - ResultItemFontSize = 16; - - ResultSubFont = "Segoe UI"; - ResultSubFontStyle = "Normal"; - ResultSubFontWeight = "Normal"; - ResultSubFontStretch = "Normal"; - ResultSubItemFontSize = 13; - - ItemHeightSize = 58; - WindowHeightSize = 42; - } } diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml index f9758389f..fd579ae17 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml @@ -116,6 +116,7 @@ TickFrequency="1" Value="{Binding QueryBoxFontSize, Mode=TwoWay}" /> Date: Sun, 26 May 2024 16:01:29 +0600 Subject: [PATCH 1408/2008] Add option to hide uninstallers from results --- .../Languages/en.xaml | 4 +++- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 23 +++++++++++++++++++ .../Flow.Launcher.Plugin.Program/Settings.cs | 3 ++- .../Views/ProgramSetting.xaml | 5 ++++ .../Views/ProgramSetting.xaml.cs | 12 +++++++++- 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml index d7e87b50b..25ceac3bb 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml @@ -32,6 +32,8 @@ When enabled, Flow will load programs from the PATH environment variable Hide app path For executable files such as UWP or lnk, hide the file path from being visible + Hide uninstallers + Hides programs with common uninstaller names, such as unins000.exe Search in Program Description Flow will search program's description Suffixes @@ -92,4 +94,4 @@ This app is not intended to be run as administrator Unable to run {0} - \ No newline at end of file + diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index e0a7f23de..8bf1830e3 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -11,6 +11,7 @@ using Flow.Launcher.Plugin.Program.Programs; using Flow.Launcher.Plugin.Program.Views; using Flow.Launcher.Plugin.Program.Views.Models; using Microsoft.Extensions.Caching.Memory; +using Path = System.IO.Path; using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher.Plugin.Program @@ -33,6 +34,17 @@ namespace Flow.Launcher.Plugin.Program private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; private static MemoryCache cache = new(cacheOptions); + private static readonly string[] commonUninstallerNames = + { + "uninst.exe", + "unins000.exe", + "uninst000.exe", + "uninstall.exe" + }; + // For cases when the uninstaller is named like "Uninstall Program Name.exe" + private const string CommonUninstallerPrefix = "uninstall"; + private const string CommonUninstallerSuffix = ".exe"; + static Main() { } @@ -52,6 +64,7 @@ namespace Flow.Launcher.Plugin.Program .Concat(_uwps) .AsParallel() .WithCancellation(token) + .Where(HideUninstallersFilter) .Where(p => p.Enabled) .Select(p => p.Result(query.Search, Context.API)) .Where(r => r?.Score > 0) @@ -68,6 +81,16 @@ namespace Flow.Launcher.Plugin.Program return result; } + private bool HideUninstallersFilter(IProgram program) + { + if (!_settings.HideUninstallers) return true; + if (program is not Win32 win32) return true; + var fileName = Path.GetFileName(win32.ExecutablePath); + return !commonUninstallerNames.Contains(fileName, StringComparer.OrdinalIgnoreCase) && + !(fileName.StartsWith(CommonUninstallerPrefix, StringComparison.OrdinalIgnoreCase) && + fileName.EndsWith(CommonUninstallerSuffix, StringComparison.OrdinalIgnoreCase)); + } + public async Task InitAsync(PluginInitContext context) { Context = context; diff --git a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs index ca203f803..fb24f64d7 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs @@ -102,7 +102,7 @@ namespace Flow.Launcher.Plugin.Program // CustomSuffixes no longer contains custom suffixes // users has tweaked the settings // or this function has been executed once - if (UseCustomSuffixes == true || ProgramSuffixes == null) + if (UseCustomSuffixes == true || ProgramSuffixes == null) return; var suffixes = ProgramSuffixes.ToList(); foreach(var item in BuiltinSuffixesStatus) @@ -117,6 +117,7 @@ namespace Flow.Launcher.Plugin.Program public bool EnableStartMenuSource { get; set; } = true; public bool EnableDescription { get; set; } = false; public bool HideAppsPath { get; set; } = true; + public bool HideUninstallers { get; set; } = false; public bool EnableRegistrySource { get; set; } = true; public bool EnablePathSource { get; set; } = false; public bool EnableUWP { get; set; } = true; diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml index fa97de4f2..e5ca6967e 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml @@ -85,6 +85,11 @@ Content="{DynamicResource flowlauncher_plugin_program_enable_hidelnkpath}" IsChecked="{Binding HideAppsPath}" ToolTip="{DynamicResource flowlauncher_plugin_program_enable_hidelnkpath_tooltip}" /> + ProgramSettingDisplayList { get; set; } public bool EnableDescription @@ -47,6 +47,16 @@ namespace Flow.Launcher.Plugin.Program.Views } } + public bool HideUninstallers + { + get => _settings.HideUninstallers; + set + { + Main.ResetCache(); + _settings.HideUninstallers = value; + } + } + public bool EnableRegistrySource { get => _settings.EnableRegistrySource; From 188c409eb4ad43d3e5ecdf838ed83fff464cedb2 Mon Sep 17 00:00:00 2001 From: DB p Date: Sun, 26 May 2024 19:08:09 +0900 Subject: [PATCH 1409/2008] Adjust Reset Logic --- .../SettingPages/Views/SettingsPaneTheme.xaml | 4 +- .../Views/SettingsPaneTheme.xaml.cs | 87 ++++++++++++++----- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml index fd579ae17..d0ef54a99 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml @@ -166,7 +166,7 @@ BorderThickness="1" Style="{StaticResource SettingSeparatorStyle}" /> Date: Sun, 26 May 2024 22:50:48 +0900 Subject: [PATCH 1410/2008] Add Keep Height (old behaiver) function --- .../UserSettings/Settings.cs | 1 + Flow.Launcher/Languages/en.xaml | 2 ++ Flow.Launcher/MainWindow.xaml.cs | 17 ++++++++++------- .../ViewModels/SettingsPaneGeneralViewModel.cs | 5 +++++ .../Views/SettingsPaneGeneral.xaml | 18 ++++++++++++++++++ 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index bf269ba12..aeb492162 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -232,6 +232,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings /// public double CustomWindowTop { get; set; } = 0; + public bool KeepMaxResults { get; set; } = false; public int MaxResultsToShow { get; set; } = 5; public int ActivateTimes { get; set; } diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 8a3cf1e80..d1b342751 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -56,6 +56,8 @@ Preserve Last Query Select last Query Empty last Query + Keeping Window Max Height + Window height will keep to fit the maximum number of results Maximum results shown You can also quickly adjust this by using CTRL+Plus and CTRL+Minus. Ignore hotkeys in fullscreen mode diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index c333b6b04..7b497f394 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -120,14 +120,17 @@ namespace Flow.Launcher shadowMargin = 32; } - if (System.Convert.ToInt32((Height - (_settings.WindowHeightSize + 14) - shadowMargin) / _settings.ItemHeightSize) < 1) - { - _settings.MaxResultsToShow = 2; - } - else - { - _settings.MaxResultsToShow = System.Convert.ToInt32(Math.Truncate((Height - (_settings.WindowHeightSize + 14) - shadowMargin) / _settings.ItemHeightSize)); + if (!_settings.KeepMaxResults) { + if (System.Convert.ToInt32((Height - (_settings.WindowHeightSize + 14) - shadowMargin) / _settings.ItemHeightSize) < 1) + { + _settings.MaxResultsToShow = 2; + } + else + { + _settings.MaxResultsToShow = System.Convert.ToInt32(Math.Truncate((Height - (_settings.WindowHeightSize + 14) - shadowMargin) / _settings.ItemHeightSize)); + } } + _settings.WindowSize = Width; FlowMainWindow.SizeToContent = SizeToContent.Height; } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index a9718a0ac..cb231d4f5 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -151,6 +151,11 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public List Languages => InternationalizationManager.Instance.LoadAvailableLanguages(); public IEnumerable MaxResultsRange => Enumerable.Range(2, 16); + public bool KeepMaxResults + { + get => Settings.KeepMaxResults; + set => Settings.KeepMaxResults = value; + } public string AlwaysPreviewToolTip => string.Format( InternationalizationManager.Instance.GetTranslation("AlwaysPreviewToolTip"), diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index c2b23a295..e983e77db 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -153,6 +153,24 @@ + + + + + + + + + Date: Mon, 27 May 2024 05:44:16 +0900 Subject: [PATCH 1411/2008] Adjust Layout for Long Label (language) Adjust Item Position --- .../SettingPages/Views/SettingsPaneTheme.xaml | 526 +++++++++--------- 1 file changed, 252 insertions(+), 274 deletions(-) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml index d0ef54a99..f3fbac4b8 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml @@ -38,10 +38,248 @@ Text="{DynamicResource appearance}" TextAlignment="left" Visibility="Collapsed" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
public bool ShouldUsePinyin { get; set; } = false; - public bool UseExternalPreview { get; set; } = false; - public bool AlwaysPreview { get; set; } = false; public bool AlwaysStartEn { get; set; } = false; diff --git a/Flow.Launcher.Plugin/Interfaces/IAsyncExternalPreview.cs b/Flow.Launcher.Plugin/Interfaces/IAsyncExternalPreview.cs index 9ee05b46c..575a422d9 100644 --- a/Flow.Launcher.Plugin/Interfaces/IAsyncExternalPreview.cs +++ b/Flow.Launcher.Plugin/Interfaces/IAsyncExternalPreview.cs @@ -2,14 +2,30 @@ namespace Flow.Launcher.Plugin { - public interface IAsyncExternalPreview: IFeatures + /// + /// This interface is for plugins that wish to provide file preview (external preview) + /// via a third party app instead of the default preview. + /// + public interface IAsyncExternalPreview : IFeatures { - public Task TogglePreviewAsync(string path); - + /// + /// Method for opening/showing the preview. + /// + /// The file path to open the preview for + /// Whether to send a toast message notification on failure for the user public Task OpenPreviewAsync(string path, bool sendFailToast = true); + /// + /// Method for closing/hiding the preview. + /// public Task ClosePreviewAsync(); + /// + /// Method for switching the preview to the next file result. + /// This requires the external preview be already open/showing + /// + /// The file path to switch the preview for + /// Whether to send a toast message notification on failure for the user public Task SwitchPreviewAsync(string path, bool sendFailToast = true); } } diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 179fc5ef8..9b42b1021 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -261,7 +261,7 @@ namespace Flow.Launcher.Plugin /// Contains data used to populate the preview section of this result. /// public PreviewInfo Preview { get; set; } = PreviewInfo.Default; - + /// /// Info of the preview section of a /// @@ -291,7 +291,7 @@ namespace Flow.Launcher.Plugin public IconDelegate PreviewDelegate { get; set; } = null; /// - /// File path of the result. For third-party preview programs such as QuickLook. + /// File path of the result. For third-party programs providing external preview. /// public string FilePath { get; set; } = null; diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 7f3ec1ff3..94a3a9695 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -768,7 +768,7 @@ namespace Flow.Launcher.ViewModel public int ResultAreaColumn { get; set; } = ResultAreaColumnPreviewShown; // This is not a reliable indicator of whether external preview is visible due to the - // ability of manually closing/exiting the external preview program, and this does not inform flow that + // ability of manually closing/exiting the external preview program which, does not inform flow that // preview is no longer available. public bool ExternalPreviewVisible { get; set; } = false; From a8e2927f2ab8b079dfe930cbbaa3e357c3f7d10d Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Thu, 30 May 2024 18:55:35 +0600 Subject: [PATCH 1452/2008] Integrate native Windows context menu directly into the Explorer plugin --- .../ContextMenu.cs | 19 + .../Helper/ShellContextMenuDisplayHelper.cs | 425 ++++++++++++++++++ 2 files changed, 444 insertions(+) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs index 2297e5f96..47521cdab 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs @@ -9,6 +9,7 @@ using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Plugin.Explorer.Search; using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; using System.Linq; +using Flow.Launcher.Plugin.Explorer.Helper; using MessageBox = System.Windows.Forms.MessageBox; using MessageBoxIcon = System.Windows.Forms.MessageBoxIcon; using MessageBoxButton = System.Windows.Forms.MessageBoxButtons; @@ -166,6 +167,24 @@ namespace Flow.Launcher.Plugin.Explorer Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uf12b") }); + if (record.Type is ResultType.File or ResultType.Folder) + { + var menuItems = ShellContextMenuDisplayHelper.GetContextMenuWithIcons(record.FullPath); + foreach (var menuItem in menuItems) + { + contextMenus.Add(new Result + { + Title = $"{menuItem.Label}", + Icon = () => menuItem.Icon, + Action = _ => + { + ShellContextMenuDisplayHelper.ExecuteContextMenuItem(record.FullPath, menuItem.CommandId); + return true; + } + }); + } + } + if (record.Type is ResultType.File or ResultType.Folder) contextMenus.Add(new Result diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs new file mode 100644 index 000000000..15c7cb6f0 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs @@ -0,0 +1,425 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace Flow.Launcher.Plugin.Explorer.Helper; + +public static class ShellContextMenuDisplayHelper +{ + #region DllImport + + [DllImport("shell32.dll")] + private static extern Int32 SHGetMalloc(out IntPtr hObject); + + [DllImport("shell32.dll")] + private static extern Int32 SHParseDisplayName( + [MarshalAs(UnmanagedType.LPWStr)] string pszName, + IntPtr pbc, + out IntPtr ppidl, + UInt32 sfgaoIn, + out UInt32 psfgaoOut + ); + + [DllImport("shell32.dll")] + private static extern Int32 SHBindToParent( + IntPtr pidl, + [MarshalAs(UnmanagedType.LPStruct)] Guid riid, + out IntPtr ppv, + ref IntPtr ppidlLast + ); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern IntPtr CreatePopupMenu(); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern bool DestroyMenu(IntPtr hMenu); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern uint GetMenuItemCount(IntPtr hMenu); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern uint GetMenuString( + IntPtr hMenu, uint uIDItem, StringBuilder lpString, int nMaxCount, uint uFlag + ); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern bool GetMenuItemInfo(IntPtr hMenu, uint uItem, bool fByPosition, ref MENUITEMINFO lpmii); + + [DllImport("gdi32.dll")] + private static extern bool DeleteObject(IntPtr hObject); + + #endregion + + #region Constants + + private const uint ContextMenuStartId = 0x0001; + private const uint ContextMenuEndId = 0x7FFF; + + #endregion + + #region Enums + + [Flags] + enum ContextMenuFlags : uint + { + Normal = 0x00000000, + DefaultOnly = 0x00000001, + VerbsOnly = 0x00000002, + Explore = 0x00000004, + NoVerbs = 0x00000008, + CanRename = 0x00000010, + NoDefault = 0x00000020, + IncludeStatic = 0x00000040, + ItemMenu = 0x00000080, + ExtendedVerbs = 0x00000100, + DisabledVerbs = 0x00000200, + AsyncVerbState = 0x00000400, + OptimizeForInvoke = 0x00000800, + SyncCascadeMenu = 0x00001000, + DoNotPickDefault = 0x00002000, + Reserved = 0xffff0000 + } + + [Flags] + enum ContextMenuInvokeCommandFlags : uint + { + Icon = 0x00000010, + Hotkey = 0x00000020, + FlagNoUi = 0x00000400, + Unicode = 0x00004000, + NoConsole = 0x00008000, + AsyncOk = 0x00100000, + NoZoneChecks = 0x00800000, + ShiftDown = 0x10000000, + ControlDown = 0x40000000, + FlagLogUsage = 0x04000000, + PointInvoke = 0x20000000 + } + + [Flags] + enum MenuItemInformationMask : uint + { + Bitmap = 0x00000080, + Checkmarks = 0x00000008, + Data = 0x00000020, + Ftype = 0x00000100, + Id = 0x00000002, + State = 0x00000001, + String = 0x00000040, + Submenu = 0x00000004, + Type = 0x00000010 + } + + enum MenuItemFtype : uint + { + Bitmap = 0x00000004, + MenuBarBreak = 0x00000020, + MenuBreak = 0x00000040, + OwnerDraw = 0x00000100, + RadioCheck = 0x00000200, + RightJustify = 0x00004000, + RightOrder = 0x00002000, + Separator = 0x00000800, + String = 0x00000000, + } + + #endregion + + private static IMalloc GetMalloc() + { + SHGetMalloc(out var pMalloc); + return (IMalloc)Marshal.GetTypedObjectForIUnknown(pMalloc, typeof(IMalloc)); + } + + public static void ExecuteContextMenuItem(string fileName, uint menuItemId) + { + var malloc = GetMalloc(); + var hr = SHParseDisplayName(fileName, IntPtr.Zero, out var pidl, 0, out _); + if (hr != 0) throw new Exception("SHParseDisplayName failed"); + + var originalPidl = pidl; + + var guid = typeof(IShellFolder).GUID; + hr = SHBindToParent(pidl, guid, out var pShellFolder, ref pidl); + if (hr != 0) throw new Exception("SHBindToParent failed"); + + var shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(pShellFolder, typeof(IShellFolder)); + hr = shellFolder.GetUIObjectOf( + IntPtr.Zero, 1, new[] { pidl }, typeof(IContextMenu).GUID, IntPtr.Zero, out var pContextMenu + ); + if (hr != 0) throw new Exception("GetUIObjectOf failed"); + + var contextMenu = (IContextMenu)Marshal.GetTypedObjectForIUnknown(pContextMenu, typeof(IContextMenu)); + + var hMenu = CreatePopupMenu(); + contextMenu.QueryContextMenu(hMenu, 0, ContextMenuStartId, ContextMenuEndId, (uint)ContextMenuFlags.Normal); + + var directory = Path.GetDirectoryName(fileName); + var invokeCommandInfo = new CMINVOKECOMMANDINFO + { + cbSize = (uint)Marshal.SizeOf(typeof(CMINVOKECOMMANDINFO)), + fMask = (uint)ContextMenuInvokeCommandFlags.Unicode, + hwnd = IntPtr.Zero, + lpVerb = (IntPtr)(menuItemId - ContextMenuStartId), + lpParameters = null, + lpDirectory = directory ?? "", + nShow = 1, + hIcon = IntPtr.Zero, + }; + + hr = contextMenu.InvokeCommand(ref invokeCommandInfo); + if (hr != 0) + { + throw new Exception($"InvokeCommand failed with code {hr:X}"); + } + + DestroyMenu(hMenu); + Marshal.ReleaseComObject(contextMenu); + Marshal.ReleaseComObject(shellFolder); + + if (originalPidl != IntPtr.Zero) + malloc.Free(originalPidl); + + Marshal.ReleaseComObject(malloc); + } + + public static List GetContextMenuWithIcons(string filePath) + { + var malloc = GetMalloc(); + var hr = SHParseDisplayName(filePath, IntPtr.Zero, out var pidl, 0, out _); + if (hr != 0) throw new Exception("SHParseDisplayName failed"); + + var originalPidl = pidl; + + var guid = typeof(IShellFolder).GUID; + hr = SHBindToParent(pidl, guid, out var pShellFolder, ref pidl); + if (hr != 0) throw new Exception("SHBindToParent failed"); + + var shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(pShellFolder, typeof(IShellFolder)); + hr = shellFolder.GetUIObjectOf( + IntPtr.Zero, 1, new[] { pidl }, typeof(IContextMenu).GUID, IntPtr.Zero, out var pContextMenu + ); + if (hr != 0) throw new Exception("GetUIObjectOf failed"); + + var contextMenu = (IContextMenu)Marshal.GetTypedObjectForIUnknown(pContextMenu, typeof(IContextMenu)); + + var hMenu = CreatePopupMenu(); + contextMenu.QueryContextMenu(hMenu, 0, ContextMenuStartId, ContextMenuEndId, (uint)ContextMenuFlags.Normal); + + var menuItems = new List(); + ProcessMenuWithIcons(hMenu, menuItems); + + DestroyMenu(hMenu); + Marshal.ReleaseComObject(contextMenu); + Marshal.ReleaseComObject(shellFolder); + + if (originalPidl != IntPtr.Zero) + malloc.Free(originalPidl); + + Marshal.ReleaseComObject(malloc); + + return menuItems; + } + + + private static void ProcessMenuWithIcons(IntPtr hMenu, List menuItems, string prefix = "") + { + uint menuCount = GetMenuItemCount(hMenu); + + for (uint i = 0; i < menuCount; i++) + { + var menuText = new StringBuilder(256); + uint result = GetMenuString(hMenu, i, menuText, menuText.Capacity, 0x400); + + if (result == 0 || string.IsNullOrWhiteSpace(menuText.ToString())) + { + continue; + } + + menuText.Replace("&", ""); + + var mii = new MENUITEMINFO + { + cbSize = (uint)Marshal.SizeOf(typeof(MENUITEMINFO)), + fMask = (uint)(MenuItemInformationMask.Bitmap | MenuItemInformationMask.Ftype | + MenuItemInformationMask.Submenu | MenuItemInformationMask.Id) + }; + + GetMenuItemInfo(hMenu, i, true, ref mii); + + if ((mii.fType & (uint)MenuItemFtype.Separator) != 0) + { + continue; + } + + IntPtr hSubMenu = GetSubMenu(hMenu, (int)i); + if (hSubMenu != IntPtr.Zero) + { + ProcessMenuWithIcons(hSubMenu, menuItems, prefix + menuText + " > "); + } + else if (!string.IsNullOrWhiteSpace(menuText.ToString())) + { + ImageSource icon = null; + if (mii.hbmpItem != IntPtr.Zero) + { + icon = GetBitmapSourceFromHBitmap(mii.hbmpItem); + } + else if (mii.hbmpChecked != IntPtr.Zero) + { + icon = GetBitmapSourceFromHBitmap(mii.hbmpChecked); + } + + menuItems.Add(new ContextMenuItem(prefix + menuText, icon, mii.wID)); + } + } + } + + private static BitmapSource GetBitmapSourceFromHBitmap(IntPtr hBitmap) + { + var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap( + hBitmap, + IntPtr.Zero, + Int32Rect.Empty, + BitmapSizeOptions.FromWidthAndHeight(32, 32) + ); + + if (!DeleteObject(hBitmap)) + { + throw new Exception("Failed to delete HBitmap."); + } + + return bitmapSource; + } +} + +#region Data Structures + +[ComImport] +[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +[Guid("000214E6-0000-0000-C000-000000000046")] +public interface IShellFolder +{ + [PreserveSig] + int ParseDisplayName( + IntPtr hwnd, IntPtr pbc, [In, MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, out uint pchEaten, + out IntPtr ppidl, ref uint pdwAttributes + ); + + [PreserveSig] + int EnumObjects(IntPtr hwnd, uint grfFlags, out IntPtr ppenumIDList); + + [PreserveSig] + int BindToObject(IntPtr pidl, IntPtr pbc, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv); + + [PreserveSig] + int BindToStorage(IntPtr pidl, IntPtr pbc, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv); + + [PreserveSig] + int CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2); + + [PreserveSig] + int CreateViewObject(IntPtr hwndOwner, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv); + + [PreserveSig] + int GetAttributesOf( + uint cidl, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] apidl, ref uint rgfInOut + ); + + [PreserveSig] + int GetUIObjectOf( + IntPtr hwndOwner, uint cidl, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] apidl, + [In, MarshalAs(UnmanagedType.LPStruct)] + Guid riid, IntPtr rgfReserved, out IntPtr ppv + ); + + [PreserveSig] + int GetDisplayNameOf(IntPtr pidl, uint uFlags, IntPtr pName); + + [PreserveSig] + int SetNameOf( + IntPtr hwnd, IntPtr pidl, [In, MarshalAs(UnmanagedType.LPWStr)] string pszName, uint uFlags, out IntPtr ppidlOut + ); +} + +[ComImport] +[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +[Guid("00000002-0000-0000-C000-000000000046")] +public interface IMalloc +{ + [PreserveSig] + IntPtr Alloc(UInt32 cb); + + [PreserveSig] + IntPtr Realloc(IntPtr pv, UInt32 cb); + + [PreserveSig] + void Free(IntPtr pv); + + [PreserveSig] + UInt32 GetSize(IntPtr pv); + + [PreserveSig] + Int16 DidAlloc(IntPtr pv); + + [PreserveSig] + void HeapMinimize(); +} + +[StructLayout(LayoutKind.Sequential)] +public struct CMINVOKECOMMANDINFO +{ + public uint cbSize; + public uint fMask; + public IntPtr hwnd; + public IntPtr lpVerb; + [MarshalAs(UnmanagedType.LPStr)] public string lpParameters; + [MarshalAs(UnmanagedType.LPStr)] public string lpDirectory; + public int nShow; + public uint dwHotKey; + public IntPtr hIcon; +} + +[StructLayout(LayoutKind.Sequential)] +public struct MENUITEMINFO +{ + public uint cbSize; + public uint fMask; + public uint fType; + public uint fState; + public uint wID; + public IntPtr hSubMenu; + public IntPtr hbmpChecked; + public IntPtr hbmpUnchecked; + public IntPtr dwItemData; + public IntPtr dwTypeData; + public uint cch; + public IntPtr hbmpItem; +} + +[ComImport] +[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +[Guid("000214E4-0000-0000-C000-000000000046")] +public interface IContextMenu +{ + [PreserveSig] + int QueryContextMenu(IntPtr hmenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags); + + [PreserveSig] + int InvokeCommand(ref CMINVOKECOMMANDINFO pici); + + [PreserveSig] + int GetCommandString(uint idcmd, uint uflags, IntPtr reserved, StringBuilder commandstring, int cch); +} + +public record ContextMenuItem(string Label, ImageSource Icon, uint CommandId); + +#endregion From 73f7f792bfd27ed8be6d39137102ae914e9a7d26 Mon Sep 17 00:00:00 2001 From: Zixu <52385367+Zissue@users.noreply.github.com> Date: Thu, 30 May 2024 16:00:45 +0200 Subject: [PATCH 1453/2008] Fixed typo in README.md 'Exlporer' -> 'Explorer' --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 858d39d1c..866cdf8b3 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ Or download the [early access version](https://github.com/Flow-Launcher/Prerelea -- Drag a file/folder to File Exlporer, or even Discord. +- Drag a file/folder to File Explorer, or even Discord. - Copy/move behavior can be change via Ctrl or Shift, and the operation is displayed on the mouse cursor. ### Windows & Control Panel Settings From 29be50478984e0b70f12f89e477188a581131ab8 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Thu, 30 May 2024 20:49:36 +0600 Subject: [PATCH 1454/2008] Implement temporary result list height increase when preview is on --- Flow.Launcher/ViewModel/MainViewModel.cs | 16 +++++++++++--- Flow.Launcher/ViewModel/ResultsViewModel.cs | 23 +++++++++++++++++++-- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index dcca3fb1a..90f1070b4 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -143,15 +143,21 @@ namespace Flow.Launcher.ViewModel ContextMenu = new ResultsViewModel(Settings) { - LeftClickResultCommand = OpenResultCommand, RightClickResultCommand = LoadContextMenuCommand + LeftClickResultCommand = OpenResultCommand, + RightClickResultCommand = LoadContextMenuCommand, + IsPreviewOn = Settings.AlwaysPreview }; Results = new ResultsViewModel(Settings) { - LeftClickResultCommand = OpenResultCommand, RightClickResultCommand = LoadContextMenuCommand + LeftClickResultCommand = OpenResultCommand, + RightClickResultCommand = LoadContextMenuCommand, + IsPreviewOn = Settings.AlwaysPreview }; History = new ResultsViewModel(Settings) { - LeftClickResultCommand = OpenResultCommand, RightClickResultCommand = LoadContextMenuCommand + LeftClickResultCommand = OpenResultCommand, + RightClickResultCommand = LoadContextMenuCommand, + IsPreviewOn = Settings.AlwaysPreview }; _selectedResults = Results; @@ -586,6 +592,10 @@ namespace Flow.Launcher.ViewModel { HidePreview(); } + + ContextMenu.IsPreviewOn = PreviewVisible; + History.IsPreviewOn = PreviewVisible; + Results.IsPreviewOn = PreviewVisible; } private void ShowPreview() diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs index 68e59009f..107372e01 100644 --- a/Flow.Launcher/ViewModel/ResultsViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs @@ -1,4 +1,5 @@ -using Flow.Launcher.Infrastructure.UserSettings; +using System; +using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using System.Collections.Generic; using System.Collections.Specialized; @@ -49,7 +50,25 @@ namespace Flow.Launcher.ViewModel #region Properties - public double MaxHeight => MaxResults * _settings.ItemHeightSize; + public bool IsPreviewOn { get; set; } + + public double MaxHeight + { + get + { + var newResultsCount = MaxResults; + if (IsPreviewOn) + { + newResultsCount = (int)Math.Ceiling(380 / _settings.ItemHeightSize); + if (newResultsCount < MaxResults) + { + newResultsCount = MaxResults; + } + } + return newResultsCount * _settings.ItemHeightSize; + } + } + public double ItemHeightSize { get => _settings.ItemHeightSize; From 0969fc12cbe3e1850135273497ef65c33be9038d Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Thu, 30 May 2024 22:44:52 +0600 Subject: [PATCH 1455/2008] Fix bitmap creation error in Explorer plugin shell integration --- .../Helper/ShellContextMenuDisplayHelper.cs | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs index 15c7cb6f0..19414fc71 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs @@ -285,19 +285,28 @@ public static class ShellContextMenuDisplayHelper private static BitmapSource GetBitmapSourceFromHBitmap(IntPtr hBitmap) { - var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap( - hBitmap, - IntPtr.Zero, - Int32Rect.Empty, - BitmapSizeOptions.FromWidthAndHeight(32, 32) - ); - - if (!DeleteObject(hBitmap)) + try { - throw new Exception("Failed to delete HBitmap."); + var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap( + hBitmap, + IntPtr.Zero, + Int32Rect.Empty, + BitmapSizeOptions.FromWidthAndHeight(32, 32) + ); + + if (!DeleteObject(hBitmap)) + { + throw new Exception("Failed to delete HBitmap."); + } + + return bitmapSource; + } + catch (COMException) + { + // ignore } - return bitmapSource; + return null; } } From 874418ae0dec392cb125d458385f07dabef0db28 Mon Sep 17 00:00:00 2001 From: DB p Date: Fri, 31 May 2024 01:48:29 +0900 Subject: [PATCH 1456/2008] Add Dev Tray Icon --- Flow.Launcher/Flow.Launcher.csproj | 6 ++++++ Flow.Launcher/Images/dev.ico | Bin 0 -> 4286 bytes Flow.Launcher/MainWindow.xaml.cs | 3 +-- Flow.Launcher/Properties/Resources.Designer.cs | 8 ++++++++ Flow.Launcher/Properties/Resources.resx | 9 ++++++--- Flow.Launcher/Resources/dev.ico | Bin 0 -> 45451 bytes 6 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 Flow.Launcher/Images/dev.ico create mode 100644 Flow.Launcher/Resources/dev.ico diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 53c1bafc7..848c52f1f 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -111,6 +111,12 @@ + + + PreserveNewest + + + diff --git a/Flow.Launcher/Images/dev.ico b/Flow.Launcher/Images/dev.ico new file mode 100644 index 0000000000000000000000000000000000000000..aba4eb2f94f42181fa1193f82a34476e81750f8c GIT binary patch literal 4286 zcmb`LSxi({7{?F#P~%JcMAD>5iHRvO6l2n$jSWy%VPt9h&|(V+h@i44Y5E{wQ5p6b zU_h2quu`fx)ItFPD{Wa6s9;)NG&Z3#5|w=!7ON?8`agH(-nn;}JB;8Zf97)L!teWk z-*=XQ5C?oYIT7}q)W1Q9BO$~Y!VvL<*f@9Lz4+IRG7b>(v}AxTYx?P8(Ji`A*hA-4 zU34!0H#(EoNvCptp_5r1bRw&L@LE`!YoT|94x%!e#rOb}2f0JrA;M(qvc;b^@h9!$ z^Kq?$IRiC83TPW78-j$dw&Fj#139qEKhGDxE`nWCCrtCd?^VoyNzT#t!p|CxZ}P8*r{5hsK2aN- z;C3k}!9KpSeX#LRx(oj1Fl2z{L|VfA3rOHu-ZMV>-sqq4gHF)zgA>ZGew?yJQh&Mi zPuX_&&y;G%0?*HPslCGY@XGTH+nww2+57pPhoUg11((IPCJuog5KF5Ce&WavAxX|g z{yO91TY?5&tD=&G2_>&%|YzHxdgtNqh^U)4IPyuJtp|AA!; zX8uuuUl*MC-{sKc1Z#Z0|M~TIT-i2gQ1`gvS>00cZE8?=Q}zsde?r+tpPX-5d6dyK zJa(?x7kTgle^MNSnQ!)A7m`S?geEsyJfUw;w*KF$O0;MoBqzsFpEf#1aP zPxYzVk={7KJNeJ$&L4dJ;omTxdHnMCekr`|;`q?bR`*UfugJtzq|-Prh^n`!2`#iL~%9<^NlH zXX|otUxk>@uRj*`Xa2c$27ETpUx2p=&52~d{V@99h3~&2ZzI1P`w#0s?E9R5to@Yv zM?VqB4g3kY^S9A|EBMV~J_XB~Eb7nmkI3?uOZvBfUx2>i&i_{CKkGmG_^jE#KE1&j zn~hoJm-&nN36%HG4nf$@2>5S--z)z7A??2w6TgYF{M*ep)xX>Ze?i?#=2hJU^Liin zBeL}u`A7Zj^KS>ABMSPq)P5rl)&*x$) zyMutg4WE4!;95yuAFCfnQ2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + ..\Resources\app.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\dev.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Images\gamemode.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/Flow.Launcher/Resources/dev.ico b/Flow.Launcher/Resources/dev.ico new file mode 100644 index 0000000000000000000000000000000000000000..5d06b9f2857b39f0b5d3395e3e7999ba6bcc3a38 GIT binary patch literal 45451 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 literal 0 HcmV?d00001 From 90fb2051c9e51e0a7a897573ae03d9164f0f9131 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 30 May 2024 14:21:07 -0500 Subject: [PATCH 1457/2008] suppress BinaryStorage.cs exception when loading --- Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs index a679643fd..2a439b8cc 100644 --- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs @@ -67,7 +67,7 @@ namespace Flow.Launcher.Infrastructure.Storage } catch (System.Exception e) { - Log.Exception($"|BinaryStorage.Deserialize|Deserialize error for file <{FilePath}>", e); + // Log.Exception($"|BinaryStorage.Deserialize|Deserialize error for file <{FilePath}>", e); return defaultData; } } From f4f519b5ae0400c795c74b39ab63f2ee2c69e6f9 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 31 May 2024 17:02:54 +1000 Subject: [PATCH 1458/2008] minor clean up --- Flow.Launcher/ViewModel/MainViewModel.cs | 30 ++++++++++-------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 94a3a9695..71a390522 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -803,15 +803,13 @@ namespace Flow.Launcher.ViewModel [RelayCommand] private void TogglePreview() { - switch (InternalPreviewVisible || ExternalPreviewVisible) + if (InternalPreviewVisible || ExternalPreviewVisible) { - case true: - HidePreview(); - break; - - case false: - ShowPreview(); - break; + HidePreview(); + } + else + { + ShowPreview(); } } @@ -857,15 +855,13 @@ namespace Flow.Launcher.ViewModel public void ResetPreview() { - switch (Settings.AlwaysPreview) + if (Settings.AlwaysPreview) { - case true: - ShowPreview(); - break; - - case false: - HidePreview(); - break; + ShowPreview(); + } + else + { + HidePreview(); } } @@ -885,7 +881,7 @@ namespace Flow.Launcher.ViewModel break; case true - when !ExternalPreviewVisible && Settings.AlwaysPreview && CanExternalPreviewSelectedResult(out var path): + when !ExternalPreviewVisible && Settings.AlwaysPreview && CanExternalPreviewSelectedResult(out var _): ShowPreview(); break; From 59fb0e5849a7c3a5ba5d383a0737828b8d449b72 Mon Sep 17 00:00:00 2001 From: DB p Date: Fri, 31 May 2024 23:49:13 +0900 Subject: [PATCH 1459/2008] - Change Explorer Plugin Icon - Add Glyph Icons for context menu in explorer plugin - Adjust WebSearch sub icons --- .../ContextMenu.cs | 9 ++++++--- .../Images/explorer.png | Bin 44763 -> 1222 bytes .../Images/gist.png | Bin 2042 -> 3127 bytes .../Images/github.png | Bin 2042 -> 3127 bytes .../Images/gmail.png | Bin 1646 -> 1351 bytes .../Images/google.png | Bin 3874 -> 2568 bytes .../Images/google_drive.png | Bin 5793 -> 2413 bytes .../Images/google_maps.png | Bin 11348 -> 2705 bytes .../Images/google_translate.png | Bin 7468 -> 2725 bytes 9 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs index 2297e5f96..d147aa330 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs @@ -276,7 +276,8 @@ namespace Flow.Launcher.Plugin.Explorer return true; }, - IcoPath = Constants.DifferentUserIconImagePath + IcoPath = Constants.DifferentUserIconImagePath, + Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\ue748"), }); } @@ -403,7 +404,8 @@ namespace Flow.Launcher.Plugin.Explorer return false; }, - IcoPath = Constants.ExcludeFromIndexImagePath + IcoPath = Constants.ExcludeFromIndexImagePath, + Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uf140"), }; } @@ -435,7 +437,8 @@ namespace Flow.Launcher.Plugin.Explorer return false; } }, - IcoPath = Constants.IndexingOptionsIconImagePath + IcoPath = Constants.IndexingOptionsIconImagePath, + Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\ue773"), }; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Images/explorer.png b/Plugins/Flow.Launcher.Plugin.Explorer/Images/explorer.png index 552b2c5bd1715bce33e57cd2f4f8927d03879912..25da8e49c8f11eaffeb9fdea793fc96774425082 100644 GIT binary patch literal 1222 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 TjU5kzfbZ!OoyVnWmS6q{5RG1u diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Images/gist.png b/Plugins/Flow.Launcher.Plugin.WebSearch/Images/gist.png index dd9fb6f001ea10d3c5eaab7c56b551a05510df18..a272f3fb5ad6eff8eace16b696e8de445d9d1077 100644 GIT binary patch literal 3127 zcmV-749N3|P)+lgQE z@I101bi?BVLOctk8v*SCK}Z4d2qHp|O|v8tZ?-}}K~M@3kAeymJ|RRP3j`8EfDkDp zI1LFTc5$j#0D-0gOMkm=89DwUR&{*Yl9AHy&;;c&P!91bJ3835od^Z9%|KA-Q1 z*XzwIEG+yH@vh46_rK4w>{5nd8X1N`*v0`s!aN>NgU91p0@p&kOJRoNxW6(C)55YW z0?QNtuh*-X$Kz?CY5FfDNq$IVvsjkRV_EhQ$8n0|S(5-5gaG!Grs+Z=+r;zy?^%{T z1&+sNQUC~yrsquFe+(VJbL36#x)cz>&9Z z-9pK9|Neb6Z{EDb9gOeVyu3VATwIJcY}kORs;bbzg9p*^d#LgdMkd@nZD&@#Cb|aqiqXM3Q8pr6dCYMp0DWxUJ_4g3zQDKzDaH zN=5N_934J<7*$tSqiff$q0Y`uq*pIrzEna?MMVWVdGe$ZUQ!XX4y^zj4oBm-Yh#wdZKorFwIA1FOJPB)SYeQC1U0t2#PFMv1;Q7Y_z#csSU>*R?`Sj`2$ST^s zd-q$jVI2T=8S4DP!om+ENs8)i0RZ68p+m?js;;h1w*_<>+8O8N<>h1NYXN{~!7z#H z@9#%eQ9K?;bLY-goQWrLS^$7enKDH-41gp_6SzJ|BuRdpHULSIcnBj}0N@GOjvYIY)wOx^=0u0A5davIHUL?ci?ss4;ph7G z>&WW5bmk5nkR;h?1b}ue z0PqM1rt{gN%F4>bNJwJ~XiFP_BuTw`T0k}d*uH(c-VpT0h!)VN2LSBDW{b+o%Jc&0 zGXg+V&nRf!x^*a9v~uN2y#QVs0iZ<>0LV1U7R{M6M{g(mG;IKqB;D0B5rfyIng(KK z!DoORB|Q@{k|gVl0B~0CQpA%dPmtBs+}x~tDS{-)Gid{mWw}PrVjOJ5K=zu|b>zqq zWeBQsE$AB~TEHr;0Psj?`SRt+>MANKO2mI10KPJ!1#nscsKd}`Nw8)Ygi!2I9s2ee5 z3tF{mm6GmZcJ=r7E7zJ%UeKUL3{A`uMX_5C0O$*FdLrx*n7JkN_Vy~*sHH}11OTrL zKLkn?#cxLgpmw;rJXKvM1`y`YpN}3rdW6h4;+dmba=_(DIy2+;5k^avyw)YG))lcck=m+}Q#MaO$2t zd(g&>8x>Hv;t`(574mpw1ci5^D59M^ccR9|#&LK2vuDqg>xFAmXTPOVDL)zjilXYr zBt0D@Nz$K30x)#e3-w)R&YV#S>~IaR`j`UT8UlfUa`(-gIa4XXyLt0w%JpPg07zDHmT+=&!`t(E{uU^4>SFc{J{4HD`JT$(mOIy22|SEQ%ThJ%g_ zuY$sz3{~-PSL32<9FB&b6%ihM9>aho;DUkz1)^R-QZQU24lU{$;&cw{7^MZQAjVpS zg@x}4f>1x)Cg$ox@x`LWta1=PzsMAtL z0Pt|qq)Fp*c!wlO1n5gR&i1Hj(`N2;A~ zG=Om{)W#A7;a{U|$bciaZQG_ep|!OY-M)QW=^vIZU8+D(pOz9zAjj>Kq=;i>;ow1 zFnXrk-rla~iweR$~sAi(ZYCRak8#sa8wI2<1lW;?c05QN6jmZM>kHWqjH zI0JZ0lB78gaOF5|63_FAvqOh2N8=F>)D7?7zh9YXLHvi2QcFt(J%P#?6HGr0bvK9JikTj$+-cO0f6J{O*7ijBcA7{^F05;f&kiR zn*M^wmM>&uS@s_m0&vRX@q9vLn|Pkj=Q!@ZSpm>AeGk50jL2p|JY`w7c%-kf3S{7VJ$!r>b5N^?JSVtr+trPoDf9@h*#D z7%CVHR_5mBcEG0p)vH$x2LPKw5c*s$*Z*jm{=3)fWydUg!Ky+Cz2DZ>me;Lx|YR)Rd RnG*m2002ovPDHLkV1g1^sEz;t literal 2042 zcmVTx-+TYML5*vDc*4rkC0@EooA{T+Owqxp=W&YYx1e9I*%WTC5-< z@+vGWpn$wAyX$ZI$G-4e_O~y*7?0$>f6YAe%roET_nUcU<{2TSWF+p?^re_6&|N)!_R=!nJOcnL%m zPzs1ByGo!5wqxYFsg2rt^ zial~$QSU=@K)lx8qn&p894>W}9fjR; zyR{)|PSH9bF136O$!Wj<5VuMvUs;zd4y;MUsEc;$2g0F9PWFxRO4qQQd7$`=I1yCK zGV7aB@ruR)@0Y*iBcElA;oQb7K4UR1iuio|=e~no*Lvxl`x{Oa%A)xb5gqW(`6j&6 zW^+Ou=S#9kF)UjI2Egugv!l6}#)%of2q{V*c9-5`G-LsAjP2Pd`T8r z#u&c{Az}o>clJ<_TY@&5Nfjv?Lgi210a3_o>1BTxxAogvt$3u%sQR^dW>F=%k9>* zr^bA}Sc8G{r+(+JI}}O&m0PM1E59epi%)9V3bO`8m9KOxCq*+~*#Iv_4JXX4#yO*+Be)CA4WMS1JdiN);!egZ;Jl(#-ezBe@i)7(cZ z^>PaCuW8kDsuTbfiI$K%Y`ocovcxN?A|>%=Q;oyitW zg~{n@F4SFK5ZO?;PFFT(ys@_iDG<^Dnc*uHnqxIJuH9(I>2hhdEfh|di)%O9 zgXDo@&v8;Cgag8N5g|Rqrq$fqwg8Hep=B>{>^V+qgqlL>;8_H|Bk_E6boVWYU?gbS zON-U3x8Vgj5D{xK(iYowS?z^7)YyPLiRUu%X~o6BpdF{nh1q1n5^pAVZPsGBYGOl9 zHcpp|yJO?r8=v5@)t_S4Y*Am)YzuHe+Cbz1T)ugmr&pUX#Tl7#%rZ1QLeHIkR;|)S zz4JywOpJ%d#rGRXh>s`UWWqi?%1x=qdxH0JirN7&;4Ae?9oESy;*t_6DcayMB_&Rm z3n2u*{^RRQcHqGNDk`3RCO{^oq@{BZy6*;YQX|wFsP`3`ba6akEg&N`+21IHAl6{u z`7b`hu8OiHk>6EO7DV1RM(tF<->nZ)BE(_No8##Ngh?kDdA1nUbOc&Gs2ZA?f`#-{oH-+-tOQNnuW-Egu4#0ZtWVQk}ko)(s*22*62sZl&{ewf?pPa%HZzeM>mGqP(Qj?ST>_)5R`A3b@wlVg% z`uR4>a_duCdSSw-JmV`J?X=@iB!(D0wI5vJ8;5?%&Cc$i9z}WU+4n*vF?v01x4XDE zK7sqe1MZDa(003v7`>i-FH}Y(?@%O1JMEfWqIbY)tO0re`W!A!_KhNh;Lx|ePGN2i zKmNsQ+_4P?bvyotKk?3c^|DrxcN}D>>>6IqRtxttZIfgw-NRUXe z2e1S5I$Z2%?#1qOvvu<(es=J?Y~8$xjMQXOlM>N+Bh`r`2mLnGU)m>c*H}Nkw2F$n z9Vzxi%9lpWkH~FBz2e=L-M++DHsV4DWQBd7y~H9Yf?_xy5PQ7&8&pf*Q&yJ*RDB7yDcLdAV(X`0`4Udpl{In89JT5IZx4OG+GO3$rFOuiM6G zF0W)XGn=~BpiR}2UXNnhsPRxAIJ~+auLq8R&MWnaNz>3ueB}E$V8y=^f8xNS#)@~~ Y|4qm?BL{offdBvi07*qoM6N<$f@DSK#{d8T diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Images/github.png b/Plugins/Flow.Launcher.Plugin.WebSearch/Images/github.png index dd9fb6f001ea10d3c5eaab7c56b551a05510df18..a272f3fb5ad6eff8eace16b696e8de445d9d1077 100644 GIT binary patch literal 3127 zcmV-749N3|P)+lgQE z@I101bi?BVLOctk8v*SCK}Z4d2qHp|O|v8tZ?-}}K~M@3kAeymJ|RRP3j`8EfDkDp zI1LFTc5$j#0D-0gOMkm=89DwUR&{*Yl9AHy&;;c&P!91bJ3835od^Z9%|KA-Q1 z*XzwIEG+yH@vh46_rK4w>{5nd8X1N`*v0`s!aN>NgU91p0@p&kOJRoNxW6(C)55YW z0?QNtuh*-X$Kz?CY5FfDNq$IVvsjkRV_EhQ$8n0|S(5-5gaG!Grs+Z=+r;zy?^%{T z1&+sNQUC~yrsquFe+(VJbL36#x)cz>&9Z z-9pK9|Neb6Z{EDb9gOeVyu3VATwIJcY}kORs;bbzg9p*^d#LgdMkd@nZD&@#Cb|aqiqXM3Q8pr6dCYMp0DWxUJ_4g3zQDKzDaH zN=5N_934J<7*$tSqiff$q0Y`uq*pIrzEna?MMVWVdGe$ZUQ!XX4y^zj4oBm-Yh#wdZKorFwIA1FOJPB)SYeQC1U0t2#PFMv1;Q7Y_z#csSU>*R?`Sj`2$ST^s zd-q$jVI2T=8S4DP!om+ENs8)i0RZ68p+m?js;;h1w*_<>+8O8N<>h1NYXN{~!7z#H z@9#%eQ9K?;bLY-goQWrLS^$7enKDH-41gp_6SzJ|BuRdpHULSIcnBj}0N@GOjvYIY)wOx^=0u0A5davIHUL?ci?ss4;ph7G z>&WW5bmk5nkR;h?1b}ue z0PqM1rt{gN%F4>bNJwJ~XiFP_BuTw`T0k}d*uH(c-VpT0h!)VN2LSBDW{b+o%Jc&0 zGXg+V&nRf!x^*a9v~uN2y#QVs0iZ<>0LV1U7R{M6M{g(mG;IKqB;D0B5rfyIng(KK z!DoORB|Q@{k|gVl0B~0CQpA%dPmtBs+}x~tDS{-)Gid{mWw}PrVjOJ5K=zu|b>zqq zWeBQsE$AB~TEHr;0Psj?`SRt+>MANKO2mI10KPJ!1#nscsKd}`Nw8)Ygi!2I9s2ee5 z3tF{mm6GmZcJ=r7E7zJ%UeKUL3{A`uMX_5C0O$*FdLrx*n7JkN_Vy~*sHH}11OTrL zKLkn?#cxLgpmw;rJXKvM1`y`YpN}3rdW6h4;+dmba=_(DIy2+;5k^avyw)YG))lcck=m+}Q#MaO$2t zd(g&>8x>Hv;t`(574mpw1ci5^D59M^ccR9|#&LK2vuDqg>xFAmXTPOVDL)zjilXYr zBt0D@Nz$K30x)#e3-w)R&YV#S>~IaR`j`UT8UlfUa`(-gIa4XXyLt0w%JpPg07zDHmT+=&!`t(E{uU^4>SFc{J{4HD`JT$(mOIy22|SEQ%ThJ%g_ zuY$sz3{~-PSL32<9FB&b6%ihM9>aho;DUkz1)^R-QZQU24lU{$;&cw{7^MZQAjVpS zg@x}4f>1x)Cg$ox@x`LWta1=PzsMAtL z0Pt|qq)Fp*c!wlO1n5gR&i1Hj(`N2;A~ zG=Om{)W#A7;a{U|$bciaZQG_ep|!OY-M)QW=^vIZU8+D(pOz9zAjj>Kq=;i>;ow1 zFnXrk-rla~iweR$~sAi(ZYCRak8#sa8wI2<1lW;?c05QN6jmZM>kHWqjH zI0JZ0lB78gaOF5|63_FAvqOh2N8=F>)D7?7zh9YXLHvi2QcFt(J%P#?6HGr0bvK9JikTj$+-cO0f6J{O*7ijBcA7{^F05;f&kiR zn*M^wmM>&uS@s_m0&vRX@q9vLn|Pkj=Q!@ZSpm>AeGk50jL2p|JY`w7c%-kf3S{7VJ$!r>b5N^?JSVtr+trPoDf9@h*#D z7%CVHR_5mBcEG0p)vH$x2LPKw5c*s$*Z*jm{=3)fWydUg!Ky+Cz2DZ>me;Lx|YR)Rd RnG*m2002ovPDHLkV1g1^sEz;t literal 2042 zcmVTx-+TYML5*vDc*4rkC0@EooA{T+Owqxp=W&YYx1e9I*%WTC5-< z@+vGWpn$wAyX$ZI$G-4e_O~y*7?0$>f6YAe%roET_nUcU<{2TSWF+p?^re_6&|N)!_R=!nJOcnL%m zPzs1ByGo!5wqxYFsg2rt^ zial~$QSU=@K)lx8qn&p894>W}9fjR; zyR{)|PSH9bF136O$!Wj<5VuMvUs;zd4y;MUsEc;$2g0F9PWFxRO4qQQd7$`=I1yCK zGV7aB@ruR)@0Y*iBcElA;oQb7K4UR1iuio|=e~no*Lvxl`x{Oa%A)xb5gqW(`6j&6 zW^+Ou=S#9kF)UjI2Egugv!l6}#)%of2q{V*c9-5`G-LsAjP2Pd`T8r z#u&c{Az}o>clJ<_TY@&5Nfjv?Lgi210a3_o>1BTxxAogvt$3u%sQR^dW>F=%k9>* zr^bA}Sc8G{r+(+JI}}O&m0PM1E59epi%)9V3bO`8m9KOxCq*+~*#Iv_4JXX4#yO*+Be)CA4WMS1JdiN);!egZ;Jl(#-ezBe@i)7(cZ z^>PaCuW8kDsuTbfiI$K%Y`ocovcxN?A|>%=Q;oyitW zg~{n@F4SFK5ZO?;PFFT(ys@_iDG<^Dnc*uHnqxIJuH9(I>2hhdEfh|di)%O9 zgXDo@&v8;Cgag8N5g|Rqrq$fqwg8Hep=B>{>^V+qgqlL>;8_H|Bk_E6boVWYU?gbS zON-U3x8Vgj5D{xK(iYowS?z^7)YyPLiRUu%X~o6BpdF{nh1q1n5^pAVZPsGBYGOl9 zHcpp|yJO?r8=v5@)t_S4Y*Am)YzuHe+Cbz1T)ugmr&pUX#Tl7#%rZ1QLeHIkR;|)S zz4JywOpJ%d#rGRXh>s`UWWqi?%1x=qdxH0JirN7&;4Ae?9oESy;*t_6DcayMB_&Rm z3n2u*{^RRQcHqGNDk`3RCO{^oq@{BZy6*;YQX|wFsP`3`ba6akEg&N`+21IHAl6{u z`7b`hu8OiHk>6EO7DV1RM(tF<->nZ)BE(_No8##Ngh?kDdA1nUbOc&Gs2ZA?f`#-{oH-+-tOQNnuW-Egu4#0ZtWVQk}ko)(s*22*62sZl&{ewf?pPa%HZzeM>mGqP(Qj?ST>_)5R`A3b@wlVg% z`uR4>a_duCdSSw-JmV`J?X=@iB!(D0wI5vJ8;5?%&Cc$i9z}WU+4n*vF?v01x4XDE zK7sqe1MZDa(003v7`>i-FH}Y(?@%O1JMEfWqIbY)tO0re`W!A!_KhNh;Lx|ePGN2i zKmNsQ+_4P?bvyotKk?3c^|DrxcN}D>>>6IqRtxttZIfgw-NRUXe z2e1S5I$Z2%?#1qOvvu<(es=J?Y~8$xjMQXOlM>N+Bh`r`2mLnGU)m>c*H}Nkw2F$n z9Vzxi%9lpWkH~FBz2e=L-M++DHsV4DWQBd7y~H9Yf?_xy5PQ7&8&pf*Q&yJ*RDB7yDcLdAV(X`0`4Udpl{In89JT5IZx4OG+GO3$rFOuiM6G zF0W)XGn=~BpiR}2UXNnhsPRxAIJ~+auLq8R&MWnaNz>3ueB}E$V8y=^f8xNS#)@~~ Y|4qm?BL{offdBvi07*qoM6N<$f@DSK#{d8T diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Images/gmail.png b/Plugins/Flow.Launcher.Plugin.WebSearch/Images/gmail.png index aaeff302023beb4f4c17b00a4889a8f0cf41e58e..e74f0d57327ad17b9906e8a4b8370f3f02630ed0 100644 GIT binary patch literal 1351 zcmaJ>X;hL46a`!Yn#e6Bjw5CtWx0@+DQ<~JjL!vek10vZQgR)v(OlAO(@cdAPnx2Z zqPdY7+L)t4jcH`Tk+LaIX(zR@1}$@GRFuJ={h4>(efPb4f4ukW<imM`tQ3m(=e!XN;UxWxI&|@A>K>G{^iHX|&$9 zUvFQSEyeVYWBL=Bfme%atevoOCv5h(a!l-EGgw3WCs7_0V3KgAU(}%^4=bn=c2(6C zxplM?W8Fo;Q#x~372}baF2#25P8*#d70>RvO4stSEUD3zD`;o$FL%bqofgen3+enI zk*95WcnJ^FZ*|yq%u$KCk(fAo$w0T#y?szLJS#NDbMAg%oD%1SpL;y`9ZZfn{7V9sy-ZQ;v zraN7kI-_2h_P@!u!sHwXH49>;yr4^CZ;G1`^m-=f{(lShUch@^*e1ZIvB z;CiqXR+5%1Xul7wNr!_Yu$m_XOjsiuy6=lY?rAO+_&|m(@Nf)%srfp}B9v+nz;4?0 zzPjw)OZ|_m1dc2@`zA?pP>&CCx zTPd{5R3MsXI)pG|2m@qH_pr}qvcUbfbnXtx#smj?)%pA2f=2)aETY1*X*jFuqWKnE zW*%(6HFz{D^Stc7DaRrwo+oIK>T8xbINJ|V7;M#`iG`$E(DrBLH|;Xw4$zBTgFe)b zQHW{>n1{NP;ZZz*O^UVwDbSGkglPHD*SR@sb${puU0!e~JPHER$%3bb4x~_%yYAr0 z&)U|BJbpQ1>%W|F2B}IpP#b2 z!%|5uyLsor;n4qN{&`p`UY~(;`55I7c^!R*=W9q&LU^Qcd zw8Jv#S%Yi}Gqy6ROirpgv2)%E|KqdKOeMgY7EX8V^V{fH+`0);XkK?bBXj=)t!P#@ literal 1646 zcmV-!29f!RP) zl3}Y6x-Bh>|suxCWylA5b8%cw1Ou(@+$z`##VAf8OUj@B6$XOw(j0Lz->^pbE@$C~jgFe_lXF)LuYG2;b@au0KJUP)~gruf_W%r%Aie8-=?50w+Y zYykqqoNeh{z`awP`cB6>Ppb)K5wI1|`{3HUwXV(`N+RwXTF}gyKmLV+*Eg<{Tv71U zH-3)BwMhkS_GfwgssU7KeC~28N%iY5$f?Z4n|q@>&(ke2+{*amo$be|-tiJjBK{Mmg7lJG zmR3FS%%>9yh~54Bq$3gYTD(dU(Pj4%zwJ&C_9ue=5t&EY0`!l_w)P4~fi2g@sc;nR znVTkokN-vG`|m)pXfcl%!Bp_wy(Ot&5%Ar$EoML$cy)Ucnai#wvT_{-x5w6gDxi-B^ITA>t_7>_u3L__GekYD2V_BuzpdJ%K};3vHtygso%O8 zB^I^VhI6AF2D3#ZG0M%tlDrg!0-=AtfwTQM zkq7=n(djDjb3@fIv8*)q`)o)y=8EKePVq4ZQXy+cs=?-eP zzla)*SZujqCI7i=C4JQmT)JyFewR$ZHGXBA@F)>*DbyG$vMkeA-N2#M8yL9qI?FgU z8lmC2Cov9uGLbs~j02z0@Z6KOV)KB5*?YYO4Npe^baH% z1lsPrpSg1vGUtQci0qGfE%G_SZ|}g_ew^O>*HComC4QulVZv{1$J=($62sIqI__A( z$;B-IxO4{XO&u-LL*ui5r}w^90EFM(fyh~_Q16o8a_q+2DM&J^q7VuisLIsZ z^eH#>s-jR63KCDINM(lj_NF_iy<`Ck_q>UmPL7Qexhz$0ykhI4;PG){`2%z}%?Czb zOu*+wjI+Z}g!AeLgb)M`AEBThNs{Ppn$O|250hTde9pP)1H zJd}B@;?f;xp&rZQmQ(5y#-^Th?dnR93=HK7Xn z6Qg^^k=s{{*<4PY3d4tFa~voK7yN2bk_4fELE51aOQZk@8eTlE$=CL&;G*1(0(e}` zu~eCAZJ!D*o@XvD@gFeb?}dJS0`fk?+JgN;V8_iOAXi=2`SZ}3I_$Vv1Z11$wH9^f zFYeFdqV6=aP4imMer_ofwHr4b?1m-U|Jrw{XS(W@WMW#slf2I;=Bn#DvrY3_Yd3DP sbVFs|jZQayeN||tVOGF&W5x^kKPqPK2vQ8>)Bpeg07*qoM6N<$f`OYWp8x;= diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Images/google.png b/Plugins/Flow.Launcher.Plugin.WebSearch/Images/google.png index 89715168489e50feca5041161ffc2e41709de77d..7c1df1f294af968b33458fc981f2c1035a82e2ac 100644 GIT binary patch literal 2568 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 diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Images/google_drive.png b/Plugins/Flow.Launcher.Plugin.WebSearch/Images/google_drive.png index ce2346a316306575202f603bca813e566f5f157e..bff02c392268c39204274c40a4d423575a4f6cf3 100644 GIT binary patch literal 2413 zcmV-z36l1SP)+8U{2P1FDK6{7znfd?{Nh{M@L6TM@L6TM@L6TM@L6T zM@J*#o=b>fO3lwOCFcE1sl{b1vGf>AEjSP{rRGlg&tOW-`r#lWG=JxF548}h{f1RdJsckYwdO@aQ{u;Hb)iXhicaj6Lw3?C65>f z^$-96*#ftS6}WCFAPjkgt?QFiGymt$oAGs#!5)dhZi()`F49ll)*-M0mo;F1pC0;i zrfLBk7ECwH@0VMmJs#1R32sLakABGV=)zF*`<1*QO>y&=ZHm9i{DBZe`XX*HMuOW7 zmPfCQWWKD-T@afbR>jP>In20a|E=Z^irxlpC+xL$^YGRKhiUreS&9Yl(rY8H{=r?q z^teSj0o*P?9y!M{9|{O(?cs3z8e7ojKeWz*FV~H=`uij@4H$zvz<7tP$;tC(KJ3%1 zS2KbRVDDQuAG~9!+Zp#L7|-NZ=iUhguG!ZBSb@U{RmlOH|HO-CxxM%tfLo$laijGv zFkXQ?a`{G^@^RThZfAdXc7Tol<(P#6Agir>?BbhZh(U3E2 zTg-l&-#36!lUG}C`vL#W9}>b2FrI)sN`XA; z4Kx5KAUt!+Y@Y+z`iAcZ?v0+hw_2UbJ(&r(X08H>n*sW z-v8cz>sU%3#TZNg`b`k(WC`5Us+%u-t=X?X-2C@lrgN&BKX4wg3~B#*ko>yV#ZdL*WiSO6k( z2EQ}yTR>|dk5-Ue{g6lLqt)WBk4uxE<&!%Pm}h~OWbe(6f;_rRu=iJctH~|VyUCpe z%oXhX$-O`;SRQRBXnq$ba8te2gq?9QZjru9uob-qv;fxRSXhDUA=rA>_*$DsqSq4K z1wC%3DG?9_gF9G(J4DcYSH^*i@AzC^qxCMg$g~jL1s@Q-RmaxkJVCDYAS{2LzcqG? z^n79g$hYbw=5avkb{os17GmZL+=udx^S4fUMS3Lq5V2My(Jp+z=<_ZO7`Yb{Y(2d! zj{@$m?s~>5_h^Exs2r#XCvY(=kFFA1{XE(pY|US$3geOD9wE64x<%$O#fm5L zBfBur`&E0^Ehik9xr(x+c&OR-@!burJ{5_AC6(mn60 z9l+$$PdiAN->=7ug-*2tIG=6ZA9Mf_h0+pLSO3!=b&@u}U$xnb)D0oo8vG#~wNRv0 z44^l9?dO`9FKb50N4O<5xmUFvkY)>h485@n3dCb-1aR;2W15-YuMP9psP?k7s2l9)K$)Ay2UYfCEo3>Pc zRU&}Nj?XkVof@X>Xx=#ps9vsUsNkC;g^TbF-;Y^ybfsgA5>{ zvpvPE?u$MQ1>)*}11NOjn03vX8%>QOo8uThGktn6tKR|CCVJ@ycSaOQ%>f;}&m7m> zWXg*w7Q7JX>Tf-7BycT7CZa&h^Vj^yqW3YiUi-0=@}dVS&f=r9v;1HENeN_McV@^J zoqnzU=l-L)xs;D8T)e~Iv9kdK!Y}-bSSXnd1yZ+9W9Q<-n5xv?SjtCDsdV9Y-~u1N zaM^m=Q*GM3^3sqmz2Zv%(W}pDZYt%cGFBYKt*J@A9K71S^fjueA<~d9{cp^%bJNVje>?ivc@W1`oYUM$DnP}TpTwtTq>t5pmI2MlJu%Uc zFMTrN!MoyP%}u0&RLP>3Mp^x~PfoluW!aj z=420F`5moENk$M#7z&+pBl4wd0|#&Er<$8bDWqQ%^8@C$rX*f#OR{EwP~@IP&O}4e z`(05>j%aQgrLgwe7vbYS&FIu@+B8Zb#Zq+_VqP3qoIyyQ!IyyQ!IyyQ! fIyyQ!Anf@+LuTD*4!M1z00000NkvXXu0mjf1Xs5a literal 5793 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 IEb!s~2PiMP(*OVf diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Images/google_maps.png b/Plugins/Flow.Launcher.Plugin.WebSearch/Images/google_maps.png index 2413eec586c05164fea01d5f24468c7a4ec449cf..b086b7b741ac79176450ab17994e8194106a8f87 100644 GIT binary patch literal 2705 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 literal 7468 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 Z^2+~zCm6 Date: Sat, 1 Jun 2024 03:08:14 +0900 Subject: [PATCH 1460/2008] - Adjust Accent Button Style --- .../Resources/CustomControlTemplate.xaml | 59 +++++++++++++++++++ Flow.Launcher/Resources/Dark.xaml | 15 +++-- Flow.Launcher/Resources/Light.xaml | 6 +- .../SettingPages/Views/SettingsPaneAbout.xaml | 20 ++++--- 4 files changed, 86 insertions(+), 14 deletions(-) diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index a53e61f8c..b3a26ab0a 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -1642,6 +1642,65 @@ 0:0:0.033 diff --git a/Flow.Launcher/Resources/Dark.xaml b/Flow.Launcher/Resources/Dark.xaml index a910108e8..2cdec3844 100644 --- a/Flow.Launcher/Resources/Dark.xaml +++ b/Flow.Launcher/Resources/Dark.xaml @@ -1605,18 +1605,23 @@ - - + + - - - + + + + + + + + True False diff --git a/Flow.Launcher/Resources/Light.xaml b/Flow.Launcher/Resources/Light.xaml index 906430343..715621aaf 100644 --- a/Flow.Launcher/Resources/Light.xaml +++ b/Flow.Launcher/Resources/Light.xaml @@ -1608,9 +1608,11 @@ - - + + + + True diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml index 15afd7741..e7e1b8757 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml @@ -43,7 +43,7 @@ TextDecorations="None"> @@ -51,7 +51,7 @@ - + - - + + - - + + @@ -75,7 +81,7 @@ Title="{DynamicResource icons}" Margin="0 14 0 0" Icon=""> - + From 41b9068dd7229b9b08d9416f246687f30eb8d5d7 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 1 Jun 2024 04:17:05 +0900 Subject: [PATCH 1461/2008] - Adjust item margins - Add subtext for "hideOnStartup" --- Flow.Launcher/Languages/en.xaml | 1 + .../Views/SettingsPaneGeneral.xaml | 24 +++++++++++-------- .../SettingPages/Views/SettingsPaneTheme.xaml | 17 +++++++------ 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 28b516757..50096b5c1 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -75,6 +75,7 @@ Auto Update Select Hide Flow Launcher on startup + Flow Launcher starts out hidden in the tray. Hide tray icon When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Query Search Precision diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 6b301e33a..a2b1a58a4 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -36,14 +36,17 @@ OnContent="{DynamicResource enable}" /> - + - + - + - + - - + + - + - + + + + + + + + + + + + + + +