-
-
Notifications
You must be signed in to change notification settings - Fork 387
Quick Switch #1018
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Quick Switch #1018
Conversation
Some threading issues seem appearing. Not sure the detailed reason. |
Okay, my main questions would be
|
I think the major use case is to sync the path of an opened explorer to a open file dialog to select a file easily.
Sry I don't get the idea. |
Okay, I understand what this is used for now. I'd have to dig a lot deeper into what the IUIAutomation can do to be able to improve this. I think the rule of thumb is to avoid sending keyboard events, and instead always use an API if one exists. Keyboard events can be delayed and whatnot. |
Yeah that's what I would like to see. It is possible to use PInvoke directly without IUIAutomation though, so it will be cool if you are familiar with that as well. Another thing is the original listary seems implement this feature without changing the textbox and sending an enter signal, so I wonder whether you may have some clues about that. |
I tried searching for what I could, but that's apparently quite tricky to hook into. So I don't really have a better solution at the moment. |
okay thanks🤣 |
There might be a alternate design: So the file manager has the "quick access" sidebar. Flow could add its own entry there, and that entry always redirects to the currently open folder. An additional advantage might be that it's easier to discover this, compared to a keyboard shortcut. Screenshot for context: (Note: I have no idea how hard that would be to efficiently pull that off.) |
So you mean to add a entry that redirect to the most recent opened explorer path?🤔Interesting |
Yep, spot-on. |
If that's the case, we may be able to create a plugin for it. |
Do you have any docs for that? |
@taooceros I haven't looked into this all that much (just a few cursory google searches) Programmatic accessApparently there's a way of programmatically adding folders to the quick access area. Special Links folderhttps://blogs.msmvps.com/kenlin/2017/06/14/537/ Steps:
Symbolic links or HardlinkI bet there's some trickery that could be done with those Extra harddriveWe could add an in-memory harddrive, mount it and provide a single shortcut in there. |
Could this be done? I really love this feature. |
Apparently Windows 11 can add files to quick access. That might let us pin a program to quick access Such a program could then update the list of files in the quick access window. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (9)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (9)
543-546
: Add logging for exception handling.catch (System.Exception ex) { - // Ignored + Log.Debug(ClassName, $"Error checking explorer window: {ex.Message}"); }
898-900
: Clear auto-switched dialogs collection in Dispose.The Dispose method should also clear the
_autoSwitchedDialogs
collection to ensure complete cleanup.// Dispose locks +lock (_autoSwitchedDialogsLock) +{ + _autoSwitchedDialogs.Clear(); +} _foregroundChangeLock.Dispose(); _navigationLock.Dispose();
411-414
: Add exception handling to prevent hotkey failures.The hotkey handler doesn't catch exceptions, which could lead to hotkey failures if the navigation logic throws exceptions.
public static void OnToggleHotkey(object sender, HotkeyEventArgs args) { - _ = Task.Run(() => NavigateDialogPathAsync(PInvoke.GetForegroundWindow())); + try + { + _ = Task.Run(async () => + { + try + { + await NavigateDialogPathAsync(PInvoke.GetForegroundWindow()); + } + catch (Exception ex) + { + Log.Exception(ClassName, "Error in NavigateDialogPathAsync from hotkey", ex); + } + }); + } + catch (Exception ex) + { + Log.Exception(ClassName, "Error processing quickswitch hotkey", ex); + } }
476-479
: Use correct lock object for thread safety.The code uses
_dialogWindowHandleLock
instead of_autoSwitchedDialogsLock
when accessing_autoSwitchedDialogs
, which could lead to race conditions.bool alreadySwitched; -lock (_dialogWindowHandleLock) +lock (_autoSwitchedDialogsLock) { alreadySwitched = _autoSwitchedDialogs.Contains(hwnd); }
644-657
: Add path existence validation.The method should validate if the path exists before attempting to jump to it.
public static async Task<bool> JumpToPathAsync(nint hwnd, string path) { // Check handle if (hwnd == nint.Zero) return false; + + // Validate path + if (string.IsNullOrEmpty(path)) + { + Log.Error(ClassName, "Path is null or empty"); + return false; + } + + if (!Path.IsPathRooted(path)) + { + Log.Error(ClassName, $"Path is not rooted: {path}"); + return false; + } // Check path if (!CheckPath(path, out var isFile)) return false;
749-751
: Fix logic error in dialog window search.The method returns the first dialog window found instead of continuing the search for a matching one.
// Update dialog window if found if (dialogWindow != null) { _quickSwitchDialogs[dialog] = dialogWindow; return dialogWindow; } - -return dialogWindow;
783-783
: Add null check for Path.GetDirectoryName result.
Path.GetDirectoryName()
can return null for root paths or invalid paths.case QuickSwitchFileResultBehaviours.Directory: Log.Debug(ClassName, $"File Jump Directory (Auto: {auto}): {path}"); - result = DirJump(Path.GetDirectoryName(path), dialog, auto); + var dirPath = Path.GetDirectoryName(path); + if (string.IsNullOrEmpty(dirPath)) + { + Log.Error(ClassName, $"Could not get directory for file: {path}"); + return false; + } + result = DirJump(dirPath, dialog, auto); break;
84-84
: ReplaceList<HWND>
withHashSet<HWND>
for better performance.Since you're frequently checking if dialogs are already switched using
Contains()
, aHashSet<HWND>
would provide O(1) lookup performance instead of O(n).-private static readonly List<HWND> _autoSwitchedDialogs = new(); +private static readonly HashSet<HWND> _autoSwitchedDialogs = new();
372-375
: Add error handling for delegate invocation.The method invokes external code but doesn't include error handling, which could lead to unhandled exceptions.
private static void InvokeUpdateQuickSwitchWindow() { - UpdateQuickSwitchWindow?.Invoke(); + try + { + UpdateQuickSwitchWindow?.Invoke(); + } + catch (Exception ex) + { + Log.Exception(ClassName, "Error updating QuickSwitch window", ex); + } }
🧹 Nitpick comments (2)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (2)
143-147
: Add logging for caught exceptions.The catch block swallows exceptions without logging them, which can make debugging difficult.
catch (System.Exception ex) { - // Ignored + Log.Debug(ClassName, $"Error refreshing last explorer: {ex.Message}"); }
621-621
: Fix typo in log message.-Log.Debug(ClassName, $"Destory dialog: {hwnd}"); +Log.Debug(ClassName, $"Destroy dialog: {hwnd}");
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs
(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (5)
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:244-247
Timestamp: 2025-06-08T14:12:21.348Z
Learning: In Flow.Launcher, App.NotifyIcon is created before MainWindow creation, so null checks for App.NotifyIcon are not necessary when accessing it from MainWindow code.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:34:24.926Z
Learning: In Windows Forms dialogs, Windows handles invalid paths and prevents the user from clicking "Ok" if the path is incorrect, so additional path validation is unnecessary.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:318-318
Timestamp: 2025-06-08T14:12:12.842Z
Learning: In Flow.Launcher, the App.NotifyIcon static property is initialized in the App class before MainWindow creation, so null checks are not needed when accessing App.NotifyIcon in MainWindow lifecycle methods.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:12:13.386Z
Learning: In Flow.Launcher, hotkey styling is implemented with a two-component structure: a Border element with style `ItemHotkeyBGStyle` that provides background and border styling, containing a TextBlock with style `ItemHotkeyStyle` that handles the text styling.
🪛 GitHub Actions: Check Spelling
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs
[warning] 12-621: Unrecognized spelling: 'NHotkey', 'VSTHRD', 'Destory', 'Ioc', 'Wnd'.
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces an experimental “Quick Switch” feature that lets users automatically or manually navigate file dialogs to the current file-manager path.
- Defined new Quick Switch interfaces, result model, and core logic in
Infrastructure/QuickSwitch
- Integrated Quick Switch into the main app, ViewModel, and explorer plugin
- Added UI settings and a default hotkey (Alt+G) for Quick Switch; updated project references
Reviewed Changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated 3 comments.
Show a summary per file
File | Description |
---|---|
Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs | Use directory var for subtitles and working dir |
Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | Implement IAsyncQuickSwitch and query adapter |
Flow.Launcher/ViewModel/MainViewModel.cs | Added Quick Switch state, cloning, and query logic |
Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml | Added hotkey control card for Quick Switch |
Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | Added Quick Switch settings cards |
Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs | Bound Quick Switch hotkey command |
Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs | Exposed EnableQuickSwitch and dropdown data |
Flow.Launcher/MainWindow.xaml.cs | Hooked Quick Switch events and position logic |
Flow.Launcher/Languages/en.xaml | Added Quick Switch UI strings |
Flow.Launcher/HotkeyControl.xaml.cs | Added QuickSwitchHotkey enum and settings |
Flow.Launcher/Helper/HotKeyMapper.cs | Register Quick Switch toggle hotkey |
Flow.Launcher/Flow.Launcher.csproj | Removed obsolete package refs |
Flow.Launcher/App.xaml.cs | Initialized Quick Switch on startup |
Flow.Launcher.Plugin/Result.cs | Minor formatting change |
Flow.Launcher.Plugin/QuickSwitchResult.cs | New QuickSwitchResult model with clone and factory |
Flow.Launcher.Plugin/Interfaces/IQuickSwitchExplorer.cs | Defined explorer plugin interface |
Flow.Launcher.Plugin/Interfaces/IQuickSwitchDialog.cs | Defined dialog plugin interface |
Flow.Launcher.Plugin/Interfaces/IQuickSwitch.cs | Defined sync Quick Switch interface |
Flow.Launcher.Plugin/Interfaces/IAsyncQuickSwitch.cs | Defined async Quick Switch interface |
Flow.Launcher.Infrastructure/Win32Helper.cs | Added window-rect and foreground helpers |
Flow.Launcher.Infrastructure/UserSettings/Settings.cs | Added Quick Switch settings and enums |
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitchPair.cs | Pair types for explorers and dialogs |
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs | Core Quick Switch implementation |
Flow.Launcher.Infrastructure/QuickSwitch/Models/WindowsExplorer.cs | Windows Explorer adapter |
Flow.Launcher.Infrastructure/QuickSwitch/Models/WindowsDialog.cs | Windows File Dialog adapter |
Flow.Launcher.Infrastructure/QuickSwitch/NativeMethods.txt | Added Win32 event constants |
Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj | Added InputSimulator and NHotkey.Wpf refs |
Flow.Launcher.Core/Plugin/PluginManager.cs | Registered Quick Switch plugins |
Comments suppressed due to low confidence (2)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs:1
- The new QuickSwitch core logic is large and complex but has no associated unit tests. Consider adding tests for path navigation, event hooks, and cancellation behavior.
using System;
Flow.Launcher/ViewModel/MainViewModel.cs:2076
- You removed the null-conditional operator on
_lastQuery
, introducing a possible NullReferenceException if_lastQuery
is null. Consider restoring?
or adding an explicit null check.
var newQuery = _lastQuery.ActionKeyword;
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (7)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (7)
411-414
: Add exception handling to prevent hotkey failures.The hotkey handler doesn't catch exceptions, which could lead to hotkey failures if the navigation logic throws.
public static void OnToggleHotkey(object sender, HotkeyEventArgs args) { - _ = Task.Run(() => NavigateDialogPathAsync(PInvoke.GetForegroundWindow())); + try + { + _ = Task.Run(async () => + { + try + { + await NavigateDialogPathAsync(PInvoke.GetForegroundWindow()); + } + catch (Exception ex) + { + Log.Exception(ClassName, "Error in NavigateDialogPathAsync from hotkey", ex); + } + }); + } + catch (Exception ex) + { + Log.Exception(ClassName, "Error processing quickswitch hotkey", ex); + } }
476-479
: Incorrect lock object used for thread safety.The code uses
_dialogWindowHandleLock
which doesn't exist in the class. Should use_autoSwitchedDialogsLock
.// Check if we have already switched for this dialog bool alreadySwitched; -lock (_dialogWindowHandleLock) +lock (_autoSwitchedDialogsLock) { alreadySwitched = _autoSwitchedDialogs.Contains(hwnd); }
593-601
: Timer operations called from non-UI thread may throw exceptions.
MoveSizeCallBack
runs on the WinEvent hook thread, butDispatcherTimer.Start/Stop
must be called on the UI thread.switch (eventType) { case PInvoke.EVENT_SYSTEM_MOVESIZESTART: - _dragMoveTimer.Start(); // Start dragging position + _dragMoveTimer.Dispatcher.BeginInvoke(() => _dragMoveTimer.Start()); break; case PInvoke.EVENT_SYSTEM_MOVESIZEEND: - _dragMoveTimer.Stop(); // Stop dragging + _dragMoveTimer.Dispatcher.BeginInvoke(() => _dragMoveTimer.Stop()); break; }
740-748
: Fix logic error in dialog window search.The method returns the first dialog window found instead of only returning when it matches the target HWND.
The current logic will return any dialog window found, not necessarily the one matching
hwnd
. Only return when a match is found:dialogWindow = dialog.Plugin.CheckDialogWindow(hwnd); -} -// Update dialog window if found -if (dialogWindow != null) -{ - _quickSwitchDialogs[dialog] = dialogWindow; - return dialogWindow; + // Update dialog window if found + if (dialogWindow != null) + { + _quickSwitchDialogs[dialog] = dialogWindow; + return dialogWindow; + } }
781-781
: Add null check for Path.GetDirectoryName result.
Path.GetDirectoryName()
can return null for root paths, which would cause issues.case QuickSwitchFileResultBehaviours.Directory: Log.Debug(ClassName, $"File Jump Directory (Auto: {auto}): {path}"); - result = DirJump(Path.GetDirectoryName(path), dialog, auto); + var dirPath = Path.GetDirectoryName(path); + if (string.IsNullOrEmpty(dirPath)) + { + Log.Error(ClassName, $"Could not get directory for file: {path}"); + return false; + } + result = DirJump(dirPath, dialog, auto); break;
754-812
: Method always returns true regardless of actual result.The
result
variable is computed but the method always returnstrue
, preventing callers from detecting failures.Move the result declaration outside the try block and return it:
private static async Task<bool> JumpToPathAsync(IQuickSwitchDialogWindowTab dialog, string path, bool isFile, bool auto = false) { // Jump after flow launcher window vanished... var dialogHandle = dialog.Handle; var timeOut = !SpinWait.SpinUntil(() => Win32Helper.IsForegroundWindow(dialogHandle), 1000); if (timeOut) return false; + bool result = false; // Assume that the dialog is in the foreground now await _navigationLock.WaitAsync(); try { - bool result; if (isFile) { // ... existing switch logic ... } // ... rest of try block ... } catch (System.Exception e) { Log.Exception(ClassName, "Failed to jump to path", e); - return false; } finally { _navigationLock.Release(); } - return true; + return result; }
846-906
: Complete resource cleanup in Dispose method.The Dispose method is missing several cleanup steps that could cause issues.
Add the missing cleanup:
// Dispose locks _foregroundChangeLock.Dispose(); -_navigationLock.Dispose(); +_navigationLock.Dispose(); + +// Clear auto-switched dialogs +lock (_autoSwitchedDialogsLock) +{ + _autoSwitchedDialogs.Clear(); +} // Stop drag move timer if (_dragMoveTimer != null) { _dragMoveTimer.Stop(); _dragMoveTimer = null; } + +// Uninitialize COM (if it was initialized) +if (_enabled) +{ + try + { + PInvoke.CoUninitialize(); + } + catch (Exception ex) + { + Log.Debug(ClassName, $"Error uninitializing COM: {ex.Message}"); + } +}
🧹 Nitpick comments (2)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (2)
83-86
: ReplaceList<HWND>
withHashSet<HWND>
for better performance.The
Contains
operation onList<T>
has O(n) time complexity. Since this is checked in the foreground change callback which fires frequently, useHashSet<HWND>
for O(1) lookups.-// A list of all file dialog windows that are auto switched already -private static readonly List<HWND> _autoSwitchedDialogs = new(); +// A set of all file dialog windows that are auto switched already +private static readonly HashSet<HWND> _autoSwitchedDialogs = new(); private static readonly object _autoSwitchedDialogsLock = new();
621-621
: Fix typo in log message."Destory" should be "Destroy".
-Log.Debug(ClassName, $"Destory dialog: {hwnd}"); +Log.Debug(ClassName, $"Destroy dialog: {hwnd}");
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs
(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (5)
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:244-247
Timestamp: 2025-06-08T14:12:21.348Z
Learning: In Flow.Launcher, App.NotifyIcon is created before MainWindow creation, so null checks for App.NotifyIcon are not necessary when accessing it from MainWindow code.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:34:24.926Z
Learning: In Windows Forms dialogs, Windows handles invalid paths and prevents the user from clicking "Ok" if the path is incorrect, so additional path validation is unnecessary.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:318-318
Timestamp: 2025-06-08T14:12:12.842Z
Learning: In Flow.Launcher, the App.NotifyIcon static property is initialized in the App class before MainWindow creation, so null checks are not needed when accessing App.NotifyIcon in MainWindow lifecycle methods.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:12:13.386Z
Learning: In Flow.Launcher, hotkey styling is implemented with a two-component structure: a Border element with style `ItemHotkeyBGStyle` that provides background and border styling, containing a TextBlock with style `ItemHotkeyStyle` that handles the text styling.
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (3)
Flow.Launcher/MainWindow.xaml.cs (1)
816-828
: Fix the spelling and forbidden pattern issue.The positioning logic correctly branches between Quick Switch and normal modes, and making the method public is appropriate for external Quick Switch integration. However, there's a spelling error and forbidden pattern issue in the comment that needs to be addressed.
Apply this diff to fix the issues:
- // Initialize call twice to work around multi-display alignment issue- https://github.com/Flow-Launcher/Flow.Launcher/issues/2910 + // Initialize call twice to resolve multi-display alignment issue- https://github.com/Flow-Launcher/Flow.Launcher/issues/2910Flow.Launcher/ViewModel/MainViewModel.cs (2)
508-508
: Add type checking before casting to QuickSwitchResultSimilar to the LoadContextMenu method, this direct cast could throw an
InvalidCastException
.- if (result is QuickSwitchResult quickSwitchResult) + if (result is QuickSwitchResult quickSwitchResult) { Win32Helper.SetForegroundWindow(DialogWindowHandle); _ = Task.Run(() => QuickSwitch.JumpToPathAsync(DialogWindowHandle, quickSwitchResult.QuickSwitchPath)); }
1829-1829
: Thread safety concerns for DialogWindowHandleThe DialogWindowHandle property lacks thread synchronization mechanisms for safe access from multiple threads.
🧹 Nitpick comments (1)
Flow.Launcher/ViewModel/MainViewModel.cs (1)
1924-1924
: Fix duplicate word in commentThe comment contains a duplicate word "the the" that should be corrected.
- // Bring focus back to the the dialog + // Bring focus back to the dialog
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
Flow.Launcher/MainWindow.xaml.cs
(11 hunks)Flow.Launcher/ViewModel/MainViewModel.cs
(15 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Flow.Launcher/ViewModel/MainViewModel.cs (9)
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3118
File: Flow.Launcher/ViewModel/MainViewModel.cs:1404-1413
Timestamp: 2024-12-08T21:12:12.060Z
Learning: In the `MainViewModel` class, the `_lastQuery` field is initialized in the constructor and is never null.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3791
File: Flow.Launcher.Core/Plugin/PluginManager.cs:293-295
Timestamp: 2025-07-01T05:46:13.251Z
Learning: In Flow.Launcher.Core/Plugin/PluginManager.cs, when checking if a plugin is modified within the PluginManager class itself, prefer using the internal static PluginModified(string id) method directly rather than going through API.PluginModified() for better performance and architectural design.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:34:24.926Z
Learning: In Windows Forms dialogs, Windows handles invalid paths and prevents the user from clicking "Ok" if the path is incorrect, so additional path validation is unnecessary.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:244-247
Timestamp: 2025-06-08T14:12:21.348Z
Learning: In Flow.Launcher, App.NotifyIcon is created before MainWindow creation, so null checks for App.NotifyIcon are not necessary when accessing it from MainWindow code.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:318-318
Timestamp: 2025-06-08T14:12:12.842Z
Learning: In Flow.Launcher, the App.NotifyIcon static property is initialized in the App class before MainWindow creation, so null checks are not needed when accessing App.NotifyIcon in MainWindow lifecycle methods.
Learnt from: taooceros
PR: Flow-Launcher/Flow.Launcher#3112
File: Flow.Launcher/ViewModel/ResultsViewModel.cs:231-239
Timestamp: 2024-12-07T18:48:14.625Z
Learning: Optimizing the LINQ operations in the method `NewResults` in `ResultsViewModel.cs` did not improve performance.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:12:13.386Z
Learning: In Flow.Launcher, hotkey styling is implemented with a two-component structure: a Border element with style `ItemHotkeyBGStyle` that provides background and border styling, containing a TextBlock with style `ItemHotkeyStyle` that handles the text styling.
Learnt from: jjw24
PR: Flow-Launcher/Flow.Launcher#2448
File: Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs:16-20
Timestamp: 2025-01-18T10:10:18.414Z
Learning: In Flow Launcher's plugin system, the PluginInitContext parameter passed to plugin constructors is guaranteed to be non-null by the plugin initialization system, making null checks unnecessary.
Flow.Launcher/MainWindow.xaml.cs (13)
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:244-247
Timestamp: 2025-06-08T14:12:21.348Z
Learning: In Flow.Launcher, App.NotifyIcon is created before MainWindow creation, so null checks for App.NotifyIcon are not necessary when accessing it from MainWindow code.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:318-318
Timestamp: 2025-06-08T14:12:12.842Z
Learning: In Flow.Launcher, the App.NotifyIcon static property is initialized in the App class before MainWindow creation, so null checks are not needed when accessing App.NotifyIcon in MainWindow lifecycle methods.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:12:13.386Z
Learning: In Flow.Launcher, hotkey styling is implemented with a two-component structure: a Border element with style `ItemHotkeyBGStyle` that provides background and border styling, containing a TextBlock with style `ItemHotkeyStyle` that handles the text styling.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3791
File: Flow.Launcher.Core/Plugin/PluginManager.cs:293-295
Timestamp: 2025-07-01T05:46:13.251Z
Learning: In Flow.Launcher.Core/Plugin/PluginManager.cs, when checking if a plugin is modified within the PluginManager class itself, prefer using the internal static PluginModified(string id) method directly rather than going through API.PluginModified() for better performance and architectural design.
Learnt from: taooceros
PR: Flow-Launcher/Flow.Launcher#2616
File: Flow.Launcher/Flow.Launcher.csproj:7-7
Timestamp: 2024-10-08T15:52:58.573Z
Learning: In the Flow Launcher project, the version number in the `Flow.Launcher.csproj` file is dynamically updated during the CI/CD process.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:20:54.978Z
Learning: In WPF applications like Flow.Launcher, Border elements cannot directly display text content and require a child element like TextBlock to handle text rendering. This separation of concerns (Border for visual container styling, TextBlock for text display) follows WPF best practices and provides greater styling flexibility.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:20:54.978Z
Learning: In WPF applications like Flow.Launcher, Border elements cannot directly display text content and require a child element like TextBlock to handle text rendering. This separation of concerns (Border for visual container styling, TextBlock for text display) follows WPF best practices and provides greater styling flexibility.
Learnt from: taooceros
PR: Flow-Launcher/Flow.Launcher#2983
File: Flow.Launcher/MainWindow.xaml.cs:191-191
Timestamp: 2024-09-21T17:57:31.445Z
Learning: Calling `InitializePosition()` multiple times is intentional to prevent DPI issues across multiple displays.
Learnt from: taooceros
PR: Flow-Launcher/Flow.Launcher#2983
File: Flow.Launcher/MainWindow.xaml.cs:191-191
Timestamp: 2024-10-08T15:52:58.573Z
Learning: Calling `InitializePosition()` multiple times is intentional to prevent DPI issues across multiple displays.
Learnt from: jjw24
PR: Flow-Launcher/Flow.Launcher#2448
File: Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs:16-20
Timestamp: 2025-01-18T10:10:18.414Z
Learning: In Flow Launcher's plugin system, the PluginInitContext parameter passed to plugin constructors is guaranteed to be non-null by the plugin initialization system, making null checks unnecessary.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3279
File: Flow.Launcher/Helper/WallpaperPathRetrieval.cs:44-46
Timestamp: 2025-02-28T07:47:24.148Z
Learning: In Flow.Launcher's WallpaperPathRetrieval class, using a `using` statement with MemoryStream when loading images with BitmapImage does not work properly, even when using BitmapCacheOption.OnLoad. The stream needs to remain open while the bitmap is in use.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3118
File: Flow.Launcher/ViewModel/MainViewModel.cs:1404-1413
Timestamp: 2024-12-08T21:12:12.060Z
Learning: In the `MainViewModel` class, the `_lastQuery` field is initialized in the constructor and is never null.
🧬 Code Graph Analysis (1)
Flow.Launcher/MainWindow.xaml.cs (3)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (2)
QuickSwitch
(19-909)InitializeQuickSwitch
(100-128)Flow.Launcher/ViewModel/MainViewModel.cs (5)
InitializeVisibilityStatus
(1837-1840)Show
(2022-2064)IsQuickSwitchWindowUnderDialog
(1842-1845)ResetQuickSwitch
(1937-1977)HideQuickSwitch
(1981-1996)Flow.Launcher.Infrastructure/Win32Helper.cs (2)
Win32Helper
(30-870)GetWindowRect
(783-801)
🪛 GitHub Check: Check Spelling
Flow.Launcher/ViewModel/MainViewModel.cs
[failure] 1924-1924:
the the
matches a line_forbidden.patterns entry: \s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s
. (forbidden-pattern)
Flow.Launcher/MainWindow.xaml.cs
[failure] 818-818:
work around
matches a line_forbidden.patterns entry: \bwork[- ]arounds?\b
. (forbidden-pattern)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Report (PR)
- GitHub Check: build
🔇 Additional comments (16)
Flow.Launcher/MainWindow.xaml.cs (7)
22-22
: LGTM!The import statement correctly adds the necessary namespace for Quick Switch functionality.
120-120
: Verify the async to sync method signature change.The method signature changed from
async void
tovoid
. Ensure that no important async operations were removed that could affect the window initialization process.
169-169
: LGTM!The visibility status initialization calls correctly set the initial state based on the startup behavior, which is essential for Quick Switch functionality.
Also applies to: 174-174
217-218
: LGTM!The Quick Switch initialization is properly placed in the window loading sequence and will set up the necessary event handlers.
232-232
: LGTM!The conditional logic appropriately disables sound effects and animations when in Quick Switch mode under a dialog, preventing interference with the Quick Switch user experience.
Also applies to: 255-255
381-384
: LGTM!The early return statements correctly prevent normal window behavior when in Quick Switch mode under a dialog, ensuring the Quick Switch positioning and interaction model works as intended.
Also applies to: 395-398, 589-593, 601-604
1379-1417
: LGTM!The Quick Switch region is well-implemented with:
- Proper delegate setup linking MainWindow to QuickSwitch infrastructure
- Robust positioning logic with appropriate null checks and error handling
- Helper methods that follow the same pattern as existing positioning methods
- Clean separation of Quick Switch-specific functionality
The implementation correctly handles window positioning relative to dialog windows and integrates seamlessly with the existing codebase architecture.
Flow.Launcher/ViewModel/MainViewModel.cs (9)
19-19
: LGTM - Clean import additionThe using directive is correctly added for the Quick Switch infrastructure.
56-56
: LGTM - Consistent empty result patternThe empty QuickSwitchResult collection follows the same pattern as the existing
_emptyResult
field for consistent handling.
291-300
: LGTM - Clean refactoring to use shared cloning methodThe refactoring to use
DeepCloneResults
with theisQuickSwitch
parameter correctly set tofalse
maintains existing functionality while enabling Quick Switch support.
1876-1876
: LGTM - Safe navigation patternThe use of optional chaining with the MainWindow cast provides safe navigation and null handling.
1998-2014
: LGTM - Well-structured cleanup methodThe
ResetWindowAsync
method properly handles the cleanup operations for Quick Switch window reset with appropriate async/await usage and state management.
2037-2037
: LGTM - Appropriate Quick Switch animation handlingThe conditional opacity logic properly disables animations during Quick Switch mode for improved user experience.
2066-2066
: LGTM - Backward-compatible API enhancementThe optional
reset
parameter with default value maintains backward compatibility while providing necessary control for Quick Switch scenarios.
2254-2254
: LGTM - Proper resource disposalThe addition of
_quickSwitchSource?.Dispose()
follows the established pattern and ensures proper cleanup of cancellation token sources.
414-414
: Add type checking before casting to QuickSwitchResultThe direct cast to
QuickSwitchResult
could throw anInvalidCastException
if the result is not of the expected type.- if (result is QuickSwitchResult quickSwitchResult) + if (result is QuickSwitchResult quickSwitchResult) { - var result = SelectedResults.SelectedItem.Result; - if (result is QuickSwitchResult quickSwitchResult) + Win32Helper.SetForegroundWindow(DialogWindowHandle); + _ = Task.Run(() => QuickSwitch.JumpToPathAsync(DialogWindowHandle, quickSwitchResult.QuickSwitchPath)); + }Likely an incorrect or invalid review comment.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (7)
Flow.Launcher/ViewModel/MainViewModel.cs (7)
408-421
: Unhandled exceptions in Quick Switch navigation task.The
Task.Run
operation for Quick Switch path navigation lacks exception handling, which could lead to unobserved exceptions if navigation fails.
501-514
: Unhandled exceptions in Quick Switch navigation task.Similar to the right-click mode, this
Task.Run
operation for Quick Switch path navigation lacks exception handling.
538-564
: Type safety issue in result casting.The cast to
QuickSwitchResult
could throwInvalidCastException
if the assumption about result types is incorrect.
1828-1846
: Thread safety concerns with Quick Switch state.The
DialogWindowHandle
and_isQuickSwitch
fields are accessed from multiple threads without synchronization, which could lead to race conditions.
1902-1932
: Cancellation token capture race condition.The cancellation token is captured after the
CancellationTokenSource
assignment, which could lead to race conditions if multiple dialogs appear before the task executes.
1937-1937
: Async void method should return Task.The
ResetQuickSwitch
method usesasync void
which prevents proper exception handling and makes testing difficult.
1981-1996
: Window handle validity check needed.The method assumes that a non-zero
DialogWindowHandle
is still valid, but Windows handles can be reused or invalidated.
🧹 Nitpick comments (2)
Flow.Launcher.Infrastructure/Win32Helper.cs (1)
807-836
: Consider the hardcoded buffer size limit.The implementation correctly uses SafeProcessHandle for resource management and appropriate error handling. However, the hardcoded buffer size of 2000 characters could potentially be insufficient for very long paths (though this is rare in practice).
Consider using a more robust approach or documenting the limitation:
- uint capacity = 2000; + uint capacity = 2000; // Should be sufficient for most paths; Windows max path ~32k charsAlternatively, you could use a larger buffer or implement retry logic with increasing buffer sizes if needed.
Flow.Launcher/ViewModel/MainViewModel.cs (1)
1924-1924
: Fix the typo in the comment.There's a duplicated word "the" in the comment.
- // Bring focus back to the the dialog + // Bring focus back to the dialog
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
Flow.Launcher.Core/Plugin/PluginManager.cs
(6 hunks)Flow.Launcher.Infrastructure/UserSettings/Settings.cs
(5 hunks)Flow.Launcher.Infrastructure/Win32Helper.cs
(4 hunks)Flow.Launcher/App.xaml.cs
(3 hunks)Flow.Launcher/Languages/en.xaml
(1 hunks)Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
(1 hunks)Flow.Launcher/ViewModel/MainViewModel.cs
(15 hunks)
✅ Files skipped from review due to trivial changes (1)
- Flow.Launcher/Languages/en.xaml
🚧 Files skipped from review as they are similar to previous changes (4)
- Flow.Launcher/App.xaml.cs
- Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
- Flow.Launcher.Core/Plugin/PluginManager.cs
- Flow.Launcher.Infrastructure/UserSettings/Settings.cs
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Flow.Launcher.Infrastructure/Win32Helper.cs (11)
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:244-247
Timestamp: 2025-06-08T14:12:21.348Z
Learning: In Flow.Launcher, App.NotifyIcon is created before MainWindow creation, so null checks for App.NotifyIcon are not necessary when accessing it from MainWindow code.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:318-318
Timestamp: 2025-06-08T14:12:12.842Z
Learning: In Flow.Launcher, the App.NotifyIcon static property is initialized in the App class before MainWindow creation, so null checks are not needed when accessing App.NotifyIcon in MainWindow lifecycle methods.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3572
File: Flow.Launcher/App.xaml.cs:214-216
Timestamp: 2025-07-06T12:21:37.927Z
Learning: In Flow Launcher, the UpdatePluginManifestAsync method in PluginsManifest.cs already has comprehensive internal try-catch handling that logs exceptions and returns false on failure rather than throwing, making external try-catch wrappers unnecessary.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3791
File: Flow.Launcher.Core/Plugin/PluginManager.cs:293-295
Timestamp: 2025-07-01T05:46:13.251Z
Learning: In Flow.Launcher.Core/Plugin/PluginManager.cs, when checking if a plugin is modified within the PluginManager class itself, prefer using the internal static PluginModified(string id) method directly rather than going through API.PluginModified() for better performance and architectural design.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#0
File: :0-0
Timestamp: 2025-04-23T15:14:49.986Z
Learning: In WPF applications like Flow.Launcher, font styling should be applied using implicit styles instead of setting the FontFamily property on individual controls. Define implicit styles in a ResourceDictionary using <Style TargetType="{x:Type Button}"> format and merge it into App.xaml, which automatically applies the font to all instances of the control type while still allowing explicit overrides where needed.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3279
File: Flow.Launcher/Helper/WallpaperPathRetrieval.cs:44-46
Timestamp: 2025-02-28T07:47:24.148Z
Learning: In Flow.Launcher's WallpaperPathRetrieval class, using a `using` statement with MemoryStream when loading images with BitmapImage does not work properly, even when using BitmapCacheOption.OnLoad. The stream needs to remain open while the bitmap is in use.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:20:54.978Z
Learning: In WPF applications like Flow.Launcher, Border elements cannot directly display text content and require a child element like TextBlock to handle text rendering. This separation of concerns (Border for visual container styling, TextBlock for text display) follows WPF best practices and provides greater styling flexibility.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:20:54.978Z
Learning: In WPF applications like Flow.Launcher, Border elements cannot directly display text content and require a child element like TextBlock to handle text rendering. This separation of concerns (Border for visual container styling, TextBlock for text display) follows WPF best practices and provides greater styling flexibility.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:12:13.386Z
Learning: In Flow.Launcher, hotkey styling is implemented with a two-component structure: a Border element with style `ItemHotkeyBGStyle` that provides background and border styling, containing a TextBlock with style `ItemHotkeyStyle` that handles the text styling.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3573
File: Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs:491-493
Timestamp: 2025-06-18T13:55:09.190Z
Learning: When opening Windows settings (like indexing options), de-elevation is not needed since these operations cannot bring security risks, even when Flow Launcher is running as administrator.
Flow.Launcher/ViewModel/MainViewModel.cs (10)
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3791
File: Flow.Launcher.Core/Plugin/PluginManager.cs:293-295
Timestamp: 2025-07-01T05:46:13.251Z
Learning: In Flow.Launcher.Core/Plugin/PluginManager.cs, when checking if a plugin is modified within the PluginManager class itself, prefer using the internal static PluginModified(string id) method directly rather than going through API.PluginModified() for better performance and architectural design.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3118
File: Flow.Launcher/ViewModel/MainViewModel.cs:1404-1413
Timestamp: 2024-12-08T21:12:12.060Z
Learning: In the `MainViewModel` class, the `_lastQuery` field is initialized in the constructor and is never null.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3572
File: Flow.Launcher/App.xaml.cs:214-216
Timestamp: 2025-07-06T12:21:37.927Z
Learning: In Flow Launcher, the UpdatePluginManifestAsync method in PluginsManifest.cs already has comprehensive internal try-catch handling that logs exceptions and returns false on failure rather than throwing, making external try-catch wrappers unnecessary.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:34:24.926Z
Learning: In Windows Forms dialogs, Windows handles invalid paths and prevents the user from clicking "Ok" if the path is incorrect, so additional path validation is unnecessary.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:244-247
Timestamp: 2025-06-08T14:12:21.348Z
Learning: In Flow.Launcher, App.NotifyIcon is created before MainWindow creation, so null checks for App.NotifyIcon are not necessary when accessing it from MainWindow code.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:318-318
Timestamp: 2025-06-08T14:12:12.842Z
Learning: In Flow.Launcher, the App.NotifyIcon static property is initialized in the App class before MainWindow creation, so null checks are not needed when accessing App.NotifyIcon in MainWindow lifecycle methods.
Learnt from: taooceros
PR: Flow-Launcher/Flow.Launcher#3112
File: Flow.Launcher/ViewModel/ResultsViewModel.cs:231-239
Timestamp: 2024-12-07T18:48:14.625Z
Learning: Optimizing the LINQ operations in the method `NewResults` in `ResultsViewModel.cs` did not improve performance.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:12:13.386Z
Learning: In Flow.Launcher, hotkey styling is implemented with a two-component structure: a Border element with style `ItemHotkeyBGStyle` that provides background and border styling, containing a TextBlock with style `ItemHotkeyStyle` that handles the text styling.
Learnt from: jjw24
PR: Flow-Launcher/Flow.Launcher#2448
File: Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs:16-20
Timestamp: 2025-01-18T10:10:18.414Z
Learning: In Flow Launcher's plugin system, the PluginInitContext parameter passed to plugin constructors is guaranteed to be non-null by the plugin initialization system, making null checks unnecessary.
🪛 GitHub Actions: Check Spelling
Flow.Launcher.Infrastructure/Win32Helper.cs
[warning] 20-20: Spell check warning: Dwm
is not a recognized word.
[warning] 45-45: Spell check warning: Dwm
is not a recognized word.
[warning] 56-56: Spell check warning: SYSTEMBACKDROP
is not a recognized word.
[warning] 57-57: Spell check warning: DWMSBT
and SYSTEMBACKDROP
are not recognized words.
[warning] 58-58: Spell check warning: DWMSBT
and SYSTEMBACKDROP
are not recognized words.
[warning] 59-59: Spell check warning: DWMSBT
and SYSTEMBACKDROP
are not recognized words.
[warning] 62-62: Spell check warning: Dwm
is not a recognized word.
[warning] 64-64: Spell check warning: DWMWA
and DWMWINDOWATTRIBUTE
are not recognized words.
[warning] 73-73: Spell check warning: Dwm
is not a recognized word.
[warning] 75-75: Spell check warning: DWMWA
and DWMWINDOWATTRIBUTE
are not recognized words.
[warning] 91-93: Spell check warning: DWMWCP
is not a recognized word.
[warning] 99-99: Spell check warning: DWMWA
and DWMWINDOWATTRIBUTE
are not recognized words.
[warning] 165-186: Spell check warning: GWL
is not a recognized word.
[warning] 204-204: Spell check warning: Wnd
is not a recognized word.
[warning] 271-271: Spell check warning: WINTAB
is not a recognized word.
[warning] 284-285: Spell check warning: Progman
and WORKERW
are not recognized words.
[warning] 540-546: Spell check warning: hkl
is not a recognized word.
[warning] 572-572: Spell check warning: nqo
is not a recognized word.
[warning] 645-669: Spell check warning: tsf
and Tsf
are not recognized words.
[warning] 705-708: Spell check warning: Noto
is not a recognized word.
[warning] 749-754: Spell check warning: noto
is not a recognized word.
[warning] 774-774: Spell check warning: noto
is not a recognized word.
[warning] 47-47: Spell check warning: DWMWINDOWATTRIBUTE
and DWMWA
are not recognized words.
[warning] 56-58: Spell check warning: DWMSBT
, TRANSIENTWINDOW
, MAINWINDOW
, and TABBEDWINDOW
are not recognized words.
[warning] 90-92: Spell check warning: DWMWCP
, DONOTROUND
, and ROUNDSMALL
are not recognized words.
[warning] 190-190: Spell check warning: toolbar
is not a recognized word.
[warning] 232-234: Spell check warning: WINTAB
, Progman
, and WORKERW
are not recognized words.
[warning] 287-287: Spell check warning: SHELLDLL
is not a recognized word.
[warning] 537-537: Spell check warning: hkl
is not a recognized word.
[warning] 570-571: Spell check warning: LCIDTo
and nqo
are not recognized words.
[warning] 574-574: Spell check warning: workaround
is not a recognized word.
[warning] 654-654: Spell check warning: DWord
is not a recognized word.
[warning] 691-691: Spell check warning: regionlanguage
is not a recognized word.
[warning] 703-703: Spell check warning: Noto
is not a recognized word.
[warning] 749-749: Spell check warning: noto
is not a recognized word.
[warning] 877-877: Spell check warning: uxtheme
is not a recognized word.
🪛 GitHub Check: Check Spelling
Flow.Launcher/ViewModel/MainViewModel.cs
[failure] 1924-1924:
the the
matches a line_forbidden.patterns entry: \s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s
. (forbidden-pattern)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: gitStream.cm
- GitHub Check: build
🔇 Additional comments (4)
Flow.Launcher.Infrastructure/Win32Helper.cs (4)
17-17
: LGTM: Required imports for new functionality.The new using statements are necessary for the SafeProcessHandle and process access rights used in the new methods.
Also applies to: 21-21
143-146
: LGTM: Consistent API design.The public overload follows the established pattern of providing both
Window
andnint
handle variants for window operations, maintaining consistency with other methods in the class.
354-362
: LGTM: Proper null checking for application lifecycle.The null check for
Application.Current
properly handles the case when the application is exiting, which is crucial for avoiding exceptions during shutdown.
783-801
: LGTM: Proper error handling and type conversion.The method correctly handles API failures by returning false and provides proper conversion from native RECT to WPF Rect. The unsafe code usage is appropriate for the PInvoke call.
This comment has been minimized.
This comment has been minimized.
@check-spelling-bot Report🔴 Please reviewSee the 📂 files view, the 📜action log, or 📝 job summary for details.
See ❌ Event descriptions for more information. Forbidden patterns 🙅 (2)In order to address this, you could change the content to not match the forbidden patterns (comments before forbidden patterns may help explain why they're forbidden), add patterns for acceptable instances, or adjust the forbidden patterns themselves. These forbidden patterns matched content: s.b. workaround(s)
Reject duplicate words
If the flagged items are 🤯 false positivesIf items relate to a ...
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (5)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (5)
598-610
: Fix cross-thread timer access.
MoveSizeCallBack
is executed on the WinEvent hook thread, not the WPF UI thread where_dragMoveTimer
was created. CallingStart()
/Stop()
directly can raise anInvalidOperationException
.case PInvoke.EVENT_SYSTEM_MOVESIZESTART: - _dragMoveTimer.Start(); + _dragMoveTimer.Dispatcher.BeginInvoke(() => _dragMoveTimer.Start()); break; case PInvoke.EVENT_SYSTEM_MOVESIZEEND: - _dragMoveTimer.Stop(); + _dragMoveTimer.Dispatcher.BeginInvoke(() => _dragMoveTimer.Stop()); break;
416-419
: Add exception handling to prevent hotkey failures.The hotkey handler doesn't catch exceptions, which could lead to hotkey failures if the navigation logic throws exceptions, potentially disrupting the application's functionality.
public static void OnToggleHotkey(object sender, HotkeyEventArgs args) { - _ = Task.Run(() => NavigateDialogPathAsync(PInvoke.GetForegroundWindow())); + try + { + _ = Task.Run(async () => + { + try + { + await NavigateDialogPathAsync(PInvoke.GetForegroundWindow()); + } + catch (Exception ex) + { + Log.Exception(ClassName, "Error in NavigateDialogPathAsync from hotkey", ex); + } + }); + } + catch (Exception ex) + { + Log.Exception(ClassName, "Error processing quickswitch hotkey", ex); + } }
791-794
: Add null check for Path.GetDirectoryName result.
Path.GetDirectoryName()
can return null for root paths or invalid paths, which would cause issues in theDirJump
method.case QuickSwitchFileResultBehaviours.Directory: Log.Debug(ClassName, $"File Jump Directory (Auto: {auto}): {path}"); - result = DirJump(Path.GetDirectoryName(path), dialog, auto); + var dirPath = Path.GetDirectoryName(path); + if (string.IsNullOrEmpty(dirPath)) + { + Log.Error(ClassName, $"Could not get directory for file: {path}"); + return false; + } + result = DirJump(dirPath, dialog, auto); break;
425-560
: Add exception handling to async void method.The
ForegroundChangeCallback
is marked withSuppressMessage
for async void, but lacks comprehensive exception handling. Any unhandled exceptions could terminate the application.[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")] private static async void ForegroundChangeCallback( // parameters... ) { + try + { await _foregroundChangeLock.WaitAsync(); try { // existing implementation... } finally { _foregroundChangeLock.Release(); } + } + catch (Exception ex) + { + Log.Exception(ClassName, "Unhandled exception in ForegroundChangeCallback", ex); + } }
134-203
: Initialize COM before using shell APIs.The
SetupQuickSwitch
method uses Windows shell APIs throughRefreshLastExplorer()
but never initializes COM. This could cause failures on some systems where COM hasn't been initialized.if (enabled) { + // Initialize COM for this thread + var hr = PInvoke.CoInitializeEx(null, COINIT.COINIT_APARTMENTTHREADED); + if (hr.Failed) + { + Log.Error(ClassName, $"Failed to initialize COM: {hr}"); + return; + } + // Check if there are explorer windows and get the topmost oneRemember to balance this with
CoUninitialize()
in theDispose()
method.
🧹 Nitpick comments (2)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (2)
87-90
: Optimize data structure for better performance.Using
List<HWND>
for_autoSwitchedDialogs
results in O(n) performance forContains
,Add
, andRemove
operations. Since these operations occur in foreground-change callbacks, consider usingHashSet<HWND>
for O(1) performance and automatic duplicate prevention.-private static readonly List<HWND> _autoSwitchedDialogs = new(); +private static readonly HashSet<HWND> _autoSwitchedDialogs = new();
628-628
: Fix typo in log message.There's a spelling error in the log message.
-Log.Debug(ClassName, $"Destory dialog: {hwnd}"); +Log.Debug(ClassName, $"Destroy dialog: {hwnd}");
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs
(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (7)
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:40:11.014Z
Learning: In Flow Launcher, when using Windows Forms dialogs (e.g., in `JsonRPCPluginSettings.cs`), path validation is enabled by default in `OpenFileDialog` and `FolderBrowserDialog`, preventing users from selecting invalid paths, but it's possible to opt out of this validation on individual dialogs.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3791
File: Flow.Launcher.Core/Plugin/PluginManager.cs:293-295
Timestamp: 2025-07-01T05:46:13.251Z
Learning: In Flow.Launcher.Core/Plugin/PluginManager.cs, when checking if a plugin is modified within the PluginManager class itself, prefer using the internal static PluginModified(string id) method directly rather than going through API.PluginModified() for better performance and architectural design.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:244-247
Timestamp: 2025-06-08T14:12:21.348Z
Learning: In Flow.Launcher, App.NotifyIcon is created before MainWindow creation, so null checks for App.NotifyIcon are not necessary when accessing it from MainWindow code.
Learnt from: Yusyuriv
PR: Flow-Launcher/Flow.Launcher#3057
File: Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs:0-0
Timestamp: 2024-11-03T07:34:24.926Z
Learning: In Windows Forms dialogs, Windows handles invalid paths and prevents the user from clicking "Ok" if the path is incorrect, so additional path validation is unnecessary.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3572
File: Flow.Launcher/App.xaml.cs:214-216
Timestamp: 2025-07-06T12:21:37.927Z
Learning: In Flow Launcher, the UpdatePluginManifestAsync method in PluginsManifest.cs already has comprehensive internal try-catch handling that logs exceptions and returns false on failure rather than throwing, making external try-catch wrappers unnecessary.
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3672
File: Flow.Launcher/MainWindow.xaml.cs:318-318
Timestamp: 2025-06-08T14:12:12.842Z
Learning: In Flow.Launcher, the App.NotifyIcon static property is initialized in the App class before MainWindow creation, so null checks are not needed when accessing App.NotifyIcon in MainWindow lifecycle methods.
Learnt from: onesounds
PR: Flow-Launcher/Flow.Launcher#3394
File: Flow.Launcher/Themes/Darker Glass.xaml:134-141
Timestamp: 2025-03-28T21:12:13.386Z
Learning: In Flow.Launcher, hotkey styling is implemented with a two-component structure: a Border element with style `ItemHotkeyBGStyle` that provides background and border styling, containing a TextBlock with style `ItemHotkeyStyle` that handles the text styling.
🪛 GitHub Actions: Check Spelling
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs
[warning] 272-42: Spell check warning: 'Wnd' is not a recognized word.
[warning] 279-86: Spell check warning: 'Wnd' is not a recognized word.
[warning] 12-14: Spell check warning: 'NHotkey' is not a recognized word.
[warning] 628-51: Spell check warning: 'Destory' is not a recognized word.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: gitStream.cm
- GitHub Check: build
🔇 Additional comments (1)
Flow.Launcher.Infrastructure/QuickSwitch/QuickSwitch.cs (1)
713-764
: Fix logic error in dialog window search.The method has flawed logic - it may return the wrong dialog window because it doesn't properly validate the HWND match before returning. Additionally, the cache isn't updated when a dialog window is found.
// Finally search for the dialog window again foreach (var dialog in _quickSwitchDialogs.Keys) { if (API.PluginModified(dialog.Metadata.ID) || // Plugin is modified dialog.Metadata.Disabled) continue; // Plugin is disabled IQuickSwitchDialogWindow dialogWindow; var existingDialogWindow = _quickSwitchDialogs[dialog]; if (existingDialogWindow != null && existingDialogWindow.Handle == hwnd) { // If the dialog window is already in the list, no need to check again dialogWindow = existingDialogWindow; } else { dialogWindow = dialog.Plugin.CheckDialogWindow(hwnd); } // Update dialog window if found if (dialogWindow != null) { _quickSwitchDialogs[dialog] = dialogWindow; - return dialogWindow; + // Only return if this dialog window matches the target HWND + if (dialogWindow.Handle == hwnd) + { + return dialogWindow; + } } } return null;⛔ Skipped due to learnings
Learnt from: Jack251970 PR: Flow-Launcher/Flow.Launcher#3791 File: Flow.Launcher.Core/Plugin/PluginManager.cs:293-295 Timestamp: 2025-07-01T05:46:13.251Z Learning: In Flow.Launcher.Core/Plugin/PluginManager.cs, when checking if a plugin is modified within the PluginManager class itself, prefer using the internal static PluginModified(string id) method directly rather than going through API.PluginModified() for better performance and architectural design.
Important
Auto quick switch is an experimental feature and it can cause some possible issues, so it is marked as experimental.
Nothing more than quickswitch. We may integrate flow's path system to this feature instead of relying explorer.
Setup Quick Switch
Use Quick Switch
Open explorer -> Open file dialog -> Use hotkey to navigate to that path.
Open file dialog -> Query window (quick switch window) fixed under file dialog -> Click results to navigate to the selected path
Quick Switch API
Implement new api interfaces to develop third party explorers & dialogs which are for dotnet plugins only.
Additionally,
Explorer
plugin already supports quick switch.Test
Todos
However, for the Save As dialog, the path does not apply immediately when the dialog is opened. It only works after switching focus to File Explorer and then returning.