-
-
Notifications
You must be signed in to change notification settings - Fork 440
IPluginHotkey Interface for Global Hotkey & Window Hotkey / Support Rename File & Folder by Hotkey or Context Menu #3770
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?
IPluginHotkey Interface for Global Hotkey & Window Hotkey / Support Rename File & Folder by Hotkey or Context Menu #3770
Conversation
🥷 Code experts: Jack251970, onesounds Jack251970, onesounds have most 👩💻 activity in the files. See details
Activity based on git-commit:
Knowledge based on git-blame:
Activity based on git-commit:
Knowledge based on git-blame:
Activity based on git-commit:
Knowledge based on git-blame:
Activity based on git-commit:
Knowledge based on git-blame:
Activity based on git-commit:
Knowledge based on git-blame:
Activity based on git-commit:
Knowledge based on git-blame:
Activity based on git-commit:
Knowledge based on git-blame:
Activity based on git-commit:
Knowledge based on git-blame:
Activity based on git-commit:
Knowledge based on git-blame:
Activity based on git-commit:
Knowledge based on git-blame:
Activity based on git-commit:
Knowledge based on git-blame: To learn more about /:\ gitStream - Visit our Docs |
This comment has been minimized.
This comment has been minimized.
Please resolve conflict. |
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: 6
♻️ Duplicate comments (1)
Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml (1)
227-228
: Spelling fix acknowledged“occurred” spelling looks correct now. Thanks for addressing the prior feedback.
🧹 Nitpick comments (6)
Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml (2)
140-140
: Use Windows-standard casing: "Run as administrator"Align with existing "Run as different user" and Windows UX wording.
- <system:String x:Key="plugin_explorer_run_as_administrator">Run As Administrator</system:String> + <system:String x:Key="plugin_explorer_run_as_administrator">Run as administrator</system:String>
215-226
: Polish rename dialog strings for clarity and consistencyTighten grammar, avoid awkward colons, and use consistent punctuation and terminology.
- <system:String x:Key="plugin_explorer_not_a_new_name">The given name: {0} was not new.</system:String> + <system:String x:Key="plugin_explorer_not_a_new_name">The name '{0}' is the same as the current name.</system:String> - <system:String x:Key="plugin_explorer_field_may_not_be_empty">{0} may not be empty.</system:String> + <system:String x:Key="plugin_explorer_field_may_not_be_empty">{0} must not be empty.</system:String> - <system:String x:Key="plugin_explorer_invalid_name">{0} is an invalid name.</system:String> + <system:String x:Key="plugin_explorer_invalid_name">{0} is not a valid name.</system:String> - <system:String x:Key="plugin_explorer_item_not_found">The specified item: {0} was not found</system:String> + <system:String x:Key="plugin_explorer_item_not_found">The specified item '{0}' was not found.</system:String> - <system:String x:Key="plugin_explorer_rename_subtitle">Open a dialog to rename file or folder</system:String> + <system:String x:Key="plugin_explorer_rename_subtitle">Open the rename dialog for the selected file or folder</system:String> - <system:String x:Key="plugin_explorer_cannot_rename">This cannot be renamed.</system:String> + <system:String x:Key="plugin_explorer_cannot_rename">This item cannot be renamed.</system:String> - <system:String x:Key="plugin_explorer_successful_rename">Successfully renamed it to: {0}</system:String> + <system:String x:Key="plugin_explorer_successful_rename">Successfully renamed to '{0}'.</system:String> - <system:String x:Key="plugin_explorer_element_already_exists">There is already a file with the name: {0} in this location</system:String> + <system:String x:Key="plugin_explorer_element_already_exists">An item named '{0}' already exists in this location.</system:String>Optional (matches onesounds’ UX suggestion): add a hint line for Enter/Esc.
+ <system:String x:Key="plugin_explorer_rename_dialog_hint">Press Enter to rename • Esc to cancel</system:String>
Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml (2)
238-240
: Nit: use uniform key namingElsewhere you use literal symbols ([ and ]). Consider “Ctrl++” instead of “Ctrl+Plus” for consistency, or keep as-is if deliberate.
309-314
: Plugin hotkey section: ensure consistent styling and disposal
- Apply the known ItemHotkeyBGStyle/ItemHotkeyStyle styling pattern (per onesounds’ theming) when populating items, to match the rest of the page.
- Ensure dynamic handlers (e.g., ChangePluginHotkey) don’t leak when the page unloads.
Flow.Launcher.Core/Plugin/PluginManager.cs (2)
589-596
: InitializePluginHotkeyInfo: consider idempotenceIf InitializePluginsAsync can run more than once in-session (edge cases), guard against duplicate _pluginHotkeyInfo entries.
Apply:
- var hotkeys = ((IPluginHotkey)plugin.Plugin).GetPluginHotkeys(); - _pluginHotkeyInfo.Add(plugin, hotkeys); + var hotkeys = ((IPluginHotkey)plugin.Plugin).GetPluginHotkeys(); + if (!_pluginHotkeyInfo.ContainsKey(plugin)) + _pluginHotkeyInfo.Add(plugin, hotkeys);
622-636
: Global ChangePluginHotkey: mirror the hardeningApply the same FirstOrDefault/setting null checks as above for symmetry and robustness.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (13)
Flow.Launcher.Core/Plugin/PluginManager.cs
(8 hunks)Flow.Launcher.Core/Resource/Internationalization.cs
(1 hunks)Flow.Launcher.Plugin/Result.cs
(2 hunks)Flow.Launcher/Languages/en.xaml
(1 hunks)Flow.Launcher/MainWindow.xaml
(0 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
(0 hunks)Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml
(5 hunks)Flow.Launcher/ViewModel/MainViewModel.cs
(2 hunks)Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs
(2 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml
(2 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
(3 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs
(6 hunks)Plugins/Flow.Launcher.Plugin.Program/Main.cs
(2 hunks)
💤 Files with no reviewable changes (2)
- Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
- Flow.Launcher/MainWindow.xaml
🚧 Files skipped from review as they are similar to previous changes (7)
- Flow.Launcher/Languages/en.xaml
- Flow.Launcher/ViewModel/MainViewModel.cs
- Flow.Launcher.Core/Resource/Internationalization.cs
- Flow.Launcher.Plugin/Result.cs
- Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs
- Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
- Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-07-01T05:46:13.251Z
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.
Applied to files:
Flow.Launcher.Core/Plugin/PluginManager.cs
📚 Learning: 2025-07-21T09:19:19.012Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3854
File: Flow.Launcher.Core/Plugin/PluginManager.cs:280-292
Timestamp: 2025-07-21T09:19:19.012Z
Learning: In Flow Launcher's PluginManager.cs, the post-initialization operations (RegisterResultsUpdatedEvent, UpdatePluginMetadataTranslation, RegisterPluginActionKeywords, DialogJump.InitializeDialogJumpPlugin, and AddPluginToLists) are designed to be exception-safe and do not require additional try-catch error handling according to the maintainer Jack251970.
Applied to files:
Flow.Launcher.Core/Plugin/PluginManager.cs
📚 Learning: 2025-03-28T21:12:13.386Z
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.
Applied to files:
Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml
🧬 Code graph analysis (2)
Plugins/Flow.Launcher.Plugin.Program/Main.cs (3)
Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs (1)
List
(471-505)Flow.Launcher.Plugin/Interfaces/IPluginHotkey.cs (1)
List
(14-14)Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs (8)
List
(213-272)List
(828-849)Win32
(296-329)Win32
(331-387)Win32
(389-427)Win32
(429-453)Win32
(591-606)Win32
(667-722)
Flow.Launcher.Core/Plugin/PluginManager.cs (6)
Flow.Launcher.Plugin/Interfaces/IPluginHotkey.cs (1)
List
(14-14)Flow.Launcher.Plugin/PluginHotkey.cs (7)
BasePluginHotkey
(11-61)BasePluginHotkey
(17-20)SearchWindowPluginHotkey
(84-97)SearchWindowPluginHotkey
(89-91)GlobalPluginHotkey
(66-79)GlobalPluginHotkey
(71-73)PluginHotkey
(118-134)Flow.Launcher.Plugin/PluginMetadata.cs (2)
PluginMetadata
(10-168)ToString
(164-167)Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs (4)
UpdatePluginHotkeyInfo
(96-198)Plugin
(200-207)Plugin
(209-213)Plugin
(216-244)Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs (1)
ChangePluginHotkey
(106-116)Flow.Launcher/Helper/HotKeyMapper.cs (1)
GlobalPluginHotkey
(663-676)
🔇 Additional comments (9)
Plugins/Flow.Launcher.Plugin.Program/Main.cs (1)
18-18
: Interface adoption looks goodImplementing IPluginHotkey here is consistent with the new hotkey architecture.
Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml (4)
134-141
: History hotkey change LGTMSwitch to “OpenHistoryHotkey” with Ctrl+H looks consistent.
152-157
: Reload plugin hotkey as non-editable F5Reasonable choice. Please verify this doesn’t collide with any in-window refresh actions.
159-169
: New first/last result presets LGTMClear, non-conflicting keys.
207-223
: Requery/GameMode/CopyPath presets LGTMStatic displays are fine given recent preset policy.
Flow.Launcher.Core/Plugin/PluginManager.cs (4)
289-292
: Order and initialization LGTMHotkey info init → settings sync → window mapping is a sane sequence.
556-561
: Return a defensive copy LGTMReturning a copy of _windowPluginHotkeys avoids external mutation.
973-994
: Event payload class LGTMShape and fields are sufficient.
556-561
: HotkeyModel correctly implements value equality for dictionary keys – it implements IEquatable.Equals(CharKey, ModifierKeys) and overrides GetHashCode (via HashCode.Combine(ModifierKeys, CharKey)), and Dictionary<TKey, TValue>’s default comparer uses IEquatable.Equals. No changes needed.
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 (1)
Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs (1)
246-251
: Fix HotkeyIds mapping for “Open current folder” result (use Id 0, not 1)This result opens the folder; it should surface the “Open containing folder” hotkey (Id 0). Id 1 is “Show context menu”.
Apply:
- HotkeyIds = new List<int> - { - 1 - }, + HotkeyIds = new List<int> + { + 0 + },
🧹 Nitpick comments (3)
Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs (3)
137-142
: Don’t advertise “Run as administrator” for folder resultsId 2 (Run as administrator) doesn’t elevate folders; the handler just opens the folder normally, which is misleading. Recommend omitting 2 from folder HotkeyIds.
Apply:
- HotkeyIds = new List<int> - { - 0, 1, 2, 3 - }, + HotkeyIds = new List<int> + { + 0, 1, 3 + },
279-290
: Return false on failure to keep Flow visible; align with folder behaviorOn exception you still return true, hiding Flow after an error. Mirror CreateFolderResult: return true only on success, false on failure.
Apply:
Action = c => { try { - OpenFile(filePath, Settings.UseLocationAsWorkingDir ? directory : string.Empty); + OpenFile(filePath, Settings.UseLocationAsWorkingDir ? directory : string.Empty); + return true; } catch (Exception ex) { Context.API.ShowMsgBox(ex.Message, Context.API.GetTranslation("plugin_explorer_openfile_error")); + return false; } - - return true; },
293-298
: Avoid magic numbers for HotkeyIdsDefine shared constants/enums for 0/1/2/3 to prevent coupling errors between this file and Main.cs.
Example (new shared type, used here and in Main.cs):
internal static class ExplorerHotkeyId { public const int OpenContainingFolder = 0; public const int ShowContextMenu = 1; public const int RunAsAdministrator = 2; public const int Rename = 3; }Then use:
HotkeyIds = new List<int> { ExplorerHotkeyId.OpenContainingFolder, ExplorerHotkeyId.ShowContextMenu, ExplorerHotkeyId.RunAsAdministrator, ExplorerHotkeyId.Rename };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
Flow.Launcher.Core/Plugin/PluginManager.cs
(8 hunks)Flow.Launcher.Core/Resource/Internationalization.cs
(1 hunks)Flow.Launcher.Infrastructure/UserSettings/Settings.cs
(4 hunks)Flow.Launcher/Languages/en.xaml
(1 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
(0 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs
(6 hunks)Plugins/Flow.Launcher.Plugin.Program/Main.cs
(2 hunks)
💤 Files with no reviewable changes (1)
- Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
🚧 Files skipped from review as they are similar to previous changes (5)
- Plugins/Flow.Launcher.Plugin.Program/Main.cs
- Flow.Launcher/Languages/en.xaml
- Flow.Launcher.Core/Resource/Internationalization.cs
- Flow.Launcher.Core/Plugin/PluginManager.cs
- Flow.Launcher.Infrastructure/UserSettings/Settings.cs
🧰 Additional context used
🧬 Code graph analysis (1)
Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs (2)
Plugins/Flow.Launcher.Plugin.Explorer/Main.cs (2)
List
(57-60)List
(135-276)Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs (1)
FilesFolders
(14-406)
🔇 Additional comments (2)
Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs (2)
2-2
: LGTM: needed import for HotkeyIdsSystem.Collections.Generic is required for the new HotkeyIds lists.
309-316
: Public wrappers for OpenFile/OpenFolder are appropriateMaking these public supports plugin hotkey actions and centralizes Everything run-count updates and messaging. Looks good.
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: 2
🧹 Nitpick comments (3)
Plugins/Flow.Launcher.Plugin.Program/Main.cs (1)
493-516
: Harden action: add path guards and unify return semantics.Guard against empty paths and consistently return true on success to align with other plugins.
Apply:
Action = (r) => { - if (r?.ContextData is UWPApp uwp) - { - Context.API.OpenDirectory(uwp.Location); - return true; - } - else if (r?.ContextData is Win32 win32) - { - Context.API.OpenDirectory(win32.ParentDirectory, win32.FullPath); - return true; - } - - return false; + if (r?.ContextData is UWPApp uwp) + { + if (!string.IsNullOrWhiteSpace(uwp.Location)) + { + Context.API.OpenDirectory(uwp.Location); + return true; + } + return false; + } + else if (r?.ContextData is Win32 win32) + { + if (!string.IsNullOrWhiteSpace(win32.ParentDirectory) && + !string.IsNullOrWhiteSpace(win32.FullPath)) + { + Context.API.OpenDirectory(win32.ParentDirectory, win32.FullPath); + return true; + } + return false; + } + return false; }Optional: add Description for UI consistency (if translation exists).
Plugins/Flow.Launcher.Plugin.Explorer/Main.cs (1)
250-268
: Fix z-order: set dialog Owner to Flow’s main window.Prevents the rename dialog from appearing behind Flow when “Hide when focus lost” is off; also matches the UX request from onesounds.
Apply:
- window.ShowDialog(); + // Ensure dialog is owned by Flow to keep it in front + var owner = System.Windows.Application.Current?.MainWindow; + if (owner != null) window.Owner = owner; + window.ShowDialog();And add the missing using at top:
+using System.Windows;
Flow.Launcher.Infrastructure/UserSettings/Settings.cs (1)
185-211
: Check PageUp/PageDown defaults for next/prev page.Common convention: PageDown => next, PageUp => previous. Current defaults appear reversed.
Apply if intended:
- private string _selectNextPageHotkey = "PageUp"; + private string _selectNextPageHotkey = "PageDown"; @@ - private string _selectPrevPageHotkey = "PageDown"; + private string _selectPrevPageHotkey = "PageUp";Also applies to: 199-211
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
Flow.Launcher.Core/Resource/Internationalization.cs
(1 hunks)Flow.Launcher.Infrastructure/UserSettings/Settings.cs
(4 hunks)Flow.Launcher/Languages/en.xaml
(1 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
(0 hunks)Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs
(2 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml
(2 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
(3 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs
(6 hunks)Plugins/Flow.Launcher.Plugin.Program/Main.cs
(2 hunks)
💤 Files with no reviewable changes (1)
- Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
🚧 Files skipped from review as they are similar to previous changes (5)
- Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs
- Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs
- Flow.Launcher/Languages/en.xaml
- Flow.Launcher.Core/Resource/Internationalization.cs
- Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-21T09:19:19.012Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3854
File: Flow.Launcher.Core/Plugin/PluginManager.cs:280-292
Timestamp: 2025-07-21T09:19:19.012Z
Learning: In Flow Launcher's PluginManager.cs, the post-initialization operations (RegisterResultsUpdatedEvent, UpdatePluginMetadataTranslation, RegisterPluginActionKeywords, DialogJump.InitializeDialogJumpPlugin, and AddPluginToLists) are designed to be exception-safe and do not require additional try-catch error handling according to the maintainer Jack251970.
Applied to files:
Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
📚 Learning: 2025-07-21T09:19:49.684Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3854
File: Flow.Launcher/App.xaml.cs:246-262
Timestamp: 2025-07-21T09:19:49.684Z
Learning: In Flow Launcher's App.xaml.cs, the asynchronous plugin initialization task (containing AbstractPluginEnvironment.PreStartPluginExecutablePathUpdate, PluginManager.LoadPlugins, PluginManager.InitializePluginsAsync, and AutoPluginUpdates) does not require additional try-catch error handling according to maintainer Jack251970, as these operations are designed to handle exceptions internally.
Applied to files:
Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
🧬 Code graph analysis (3)
Plugins/Flow.Launcher.Plugin.Program/Main.cs (6)
Plugins/Flow.Launcher.Plugin.Explorer/Main.cs (3)
Main
(18-277)List
(57-60)List
(135-276)Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs (1)
Main
(11-103)Flow.Launcher/PublicAPIInstance.cs (4)
List
(252-252)List
(519-519)GetTranslation
(250-250)OpenDirectory
(331-411)Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs (1)
List
(471-505)Flow.Launcher.Plugin/Interfaces/IPluginHotkey.cs (1)
List
(14-14)Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs (8)
List
(213-272)List
(828-849)Win32
(296-329)Win32
(331-387)Win32
(389-427)Win32
(429-453)Win32
(591-606)Win32
(667-722)
Plugins/Flow.Launcher.Plugin.Explorer/Main.cs (4)
Flow.Launcher/PublicAPIInstance.cs (4)
GetTranslation
(250-250)OpenDirectory
(331-411)LogException
(286-287)ShowMsgError
(122-123)Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs (1)
Settings
(13-205)Flow.Launcher.Plugin/PluginHotkey.cs (4)
BasePluginHotkey
(11-61)BasePluginHotkey
(17-20)SearchWindowPluginHotkey
(84-97)SearchWindowPluginHotkey
(89-91)Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs (4)
ResultManager
(16-369)OpenFolder
(315-319)ShowNativeContextMenu
(74-93)OpenFile
(309-313)
Flow.Launcher.Infrastructure/UserSettings/Settings.cs (1)
Flow.Launcher/Helper/HotKeyMapper.cs (6)
RegisteredHotkeyData
(327-330)RegisteredHotkeyData
(332-337)RegisteredHotkeyData
(354-359)RegisteredHotkeyData
(361-372)RegisteredHotkeyData
(374-381)RegisteredHotkeyData
(634-639)
🔇 Additional comments (4)
Plugins/Flow.Launcher.Plugin.Program/Main.cs (2)
18-18
: Good: Program plugin now declares hotkeys via IPluginHotkey.This aligns Program with the new hotkey architecture.
493-516
: Hotkey badge: Program results already set HotkeyId 0 — no change required.HotkeyIds = new List { 0 } is present in Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs:462 and Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs:203.
Flow.Launcher.Infrastructure/UserSettings/Settings.cs (1)
73-295
: Backed hotkey properties with change notifications — looks good.This unblocks live re-registration and UI updates.
Plugins/Flow.Launcher.Plugin.Explorer/Main.cs (1)
242-275
: ESC-to-close rename dialog — implemented. RenameFile wires Escape to Close via the window.KeyDown handler in Plugins/Flow.Launcher.Plugin.Explorer/Views/RenameFile.xaml.cs (constructor, ~lines 43–47); no change required.
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: 2
🧹 Nitpick comments (5)
Plugins/Flow.Launcher.Plugin.Explorer/Views/RenameFile.xaml.cs (2)
26-27
: Remove unused field_oldFilePath
.It’s assigned but never used.
Apply this diff:
- private readonly string _oldFilePath; @@ - _oldFilePath = _info.FullName;Also applies to: 33-33
69-73
: Keep the dialog open on rename failure (improves UX).Currently the window closes regardless of success; users must reopen after an error. Consider making Rename return a bool and only close on success.
Apply this diff here after adjusting RenameThing (see helper file comment):
- RenameThing.Rename(NewFileName, _info); - Close(); + if (RenameThing.Rename(NewFileName, _info)) + { + Close(); + }Plugins/Flow.Launcher.Plugin.Explorer/Helper/RenameThing.cs (3)
22-27
: Treat same-path comparisons using OS-appropriate semantics (case-only rename).On Windows, paths are case-insensitive; current check may block case-only renames or misclassify as “already exists”.
Apply this diff and add
using System.Runtime.InteropServices;
if needed:- if (info.FullName == newPath) + if (string.Equals(Path.GetFullPath(info.FullName), Path.GetFullPath(newPath), + OperatingSystem.IsWindows() ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) { throw new NotANewNameException("New name was the same as the old name"); }Optionally, handle case-only rename by doing a temp hop on Windows if needed.
Also applies to: 41-47
56-63
: Return success status to let callers keep the dialog open on failure.Returning a bool enables better UX in the dialog. Existing behavior can be preserved by adding an overload if there are other callers.
Apply this diff:
- public static void Rename(string NewFileName, FileSystemInfo oldInfo) + public static bool Rename(string NewFileName, FileSystemInfo oldInfo) { @@ - Main.Context.API.ShowMsgError(Localize.plugin_explorer_field_may_not_be_empty()); - return; + Main.Context.API.ShowMsgError(Localize.plugin_explorer_field_may_not_be_empty()); + return false; @@ - oldInfo.Rename(NewFileName); + oldInfo.Rename(NewFileName); } catch (Exception exception) { switch (exception) { case FileNotFoundException: Main.Context.API.ShowMsgError(Localize.plugin_explorer_item_not_found(oldInfo.FullName)); - return; + return false; case NotANewNameException: Main.Context.API.ShowMsgError(Localize.plugin_explorer_not_a_new_name(NewFileName)); - return; + return false; case InvalidNameException: Main.Context.API.ShowMsgError(Localize.plugin_explorer_invalid_name(NewFileName)); - return; + return false; case ElementAlreadyExistsException: Main.Context.API.ShowMsgError(Localize.plugin_explorer_element_already_exists(NewFileName)); - return; + return false; default: string msg = exception.Message; if (!string.IsNullOrEmpty(msg)) { Main.Context.API.ShowMsgError(Localize.plugin_explorer_exception(exception.Message)); - return; + return false; } else { Main.Context.API.ShowMsgError(Localize.plugin_explorer_no_reason_given_exception()); } - - return; + return false; } } Main.Context.API.ShowMsg(Localize.plugin_explorer_successful_rename(NewFileName)); - } + return true; + }If other call sites depend on void, we can add a
TryRename
wrapper that returns bool and keepRename
as-is.Also applies to: 107-108
59-62
: Fix XML doc to match signature.The
api
parameter doc is stale.Apply this diff:
- /// <param name="api">An instance of <see cref="IPublicAPI"/>so this can create msgboxes</param>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
(0 hunks)Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs
(2 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Helper/RenameThing.cs
(1 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml
(2 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
(3 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Views/RenameFile.xaml.cs
(1 hunks)
💤 Files with no reviewable changes (1)
- Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
🚧 Files skipped from review as they are similar to previous changes (3)
- Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
- Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml
- Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-06T12:21:37.947Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3572
File: Flow.Launcher/App.xaml.cs:214-216
Timestamp: 2025-07-06T12:21:37.947Z
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.
Applied to files:
Plugins/Flow.Launcher.Plugin.Explorer/Helper/RenameThing.cs
🧬 Code graph analysis (2)
Plugins/Flow.Launcher.Plugin.Explorer/Views/RenameFile.xaml.cs (2)
Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs (2)
INotifyPropertyChanged
(9-114)OnDoneButtonClick
(45-77)Plugins/Flow.Launcher.Plugin.Explorer/Helper/RenameThing.cs (3)
RenameThing
(7-109)Rename
(9-54)Rename
(62-108)
Plugins/Flow.Launcher.Plugin.Explorer/Helper/RenameThing.cs (3)
Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs (3)
FilesFolders
(14-406)IsValidFileName
(371-379)IsValidDirectoryName
(384-393)Plugins/Flow.Launcher.Plugin.Explorer/Main.cs (1)
Main
(18-277)Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs (3)
ShowMsgError
(85-85)ShowMsg
(128-128)ShowMsg
(137-137)
⏰ 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). (1)
- GitHub Check: build
🔇 Additional comments (3)
Plugins/Flow.Launcher.Plugin.Explorer/Views/RenameFile.xaml.cs (2)
41-47
: ESC-to-close: LGTM.Key handler is straightforward; once z-order is addressed, behavior matches UX ask.
38-47
: Keep the rename dialog above Flow — set Owner and activate on loadFixes the reported z-order when “Hide Flow when focus is lost” is off: assign Owner, center on owner when available, and Activate() on Loaded.
File: Plugins/Flow.Launcher.Plugin.Explorer/Views/RenameFile.xaml.cs
Test with:
- Hide Flow when focus is lost: off
- Foremost/Topmost: on and off
Apply this diff:
ShowInTaskbar = false; RenameTb.Focus(); - var window = Window.GetWindow(this); - window.KeyDown += (s, e) => + // Keep dialog above Flow by setting owner/activation + Owner = Application.Current?.MainWindow; + WindowStartupLocation = Owner != null ? WindowStartupLocation.CenterOwner : WindowStartupLocation.CenterScreen; + Loaded += (_, __) => + { + Activate(); // bring to front + }; + + var window = Window.GetWindow(this); + window.KeyDown += (s, e) => { if (e.Key == Key.Escape) { Close(); } };Plugins/Flow.Launcher.Plugin.Explorer/Helper/RenameThing.cs (1)
18-21
: Don’t silently return when root path is empty; and avoid root-directory fallback.Returning early makes the caller think the rename succeeded (success toast is shown). Also, falling back to
new DirectoryInfo(rootPath)
for a null parent was previously flagged. Throw instead so the caller shows an error.Apply this diff:
- DirectoryInfo directory; - var rootPath = Path.GetPathRoot(file.FullName); - if (string.IsNullOrEmpty(rootPath)) return; - directory = file.Directory ?? new DirectoryInfo(rootPath); + var directory = file.Directory ?? throw new InvalidOperationException("Cannot determine parent directory for the file."); @@ - DirectoryInfo parent; - var rootPath = Path.GetPathRoot(directory.FullName); - if (string.IsNullOrEmpty(rootPath)) return; - parent = directory.Parent ?? new DirectoryInfo(rootPath); + var parent = directory.Parent ?? throw new InvalidOperationException("Cannot rename a root directory.");Also applies to: 37-40
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…name isn’t found Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Flow.Launcher/Helper/HotKeyMapper.cs (1)
451-477
: ChefKeys lifecycle: avoid stopping engine while other Win-key hotkeys remainStopping ChefKeys on any unregistration can disable other LWin/RWin bindings. Track registrations; Start on first, Stop on last.
Apply:
- private static void SetGlobalHotkeyWithChefKeys(RegisteredHotkeyData hotkeyData) + private static void SetGlobalHotkeyWithChefKeys(RegisteredHotkeyData hotkeyData) { var hotkey = hotkeyData.Hotkey; if (hotkey.IsEmpty) { return; } var hotkeyStr = hotkey.ToString(); var hotkeyCommand = hotkeyData.Command; var hotkeyCommandParameter = hotkeyData.CommandParameter; try { - ChefKeysManager.RegisterHotkey(hotkeyStr, hotkeyStr, () => hotkeyCommand.Execute(hotkeyCommandParameter)); - ChefKeysManager.Start(); + ChefKeysManager.RegisterHotkey(hotkeyStr, hotkeyStr, () => hotkeyCommand.Execute(hotkeyCommandParameter)); + lock (_chefKeysSync) + { + if (_chefKeysRefCount++ == 0) + ChefKeysManager.Start(); + } } catch (Exception e) { App.API.LogError(ClassName, string.Format("Error registering hotkey: {0} \nStackTrace:{1}", e.Message, e.StackTrace)); string errorMsg = Localize.registerHotkeyFailed(hotkeyStr); string errorMsgTitle = Localize.MessageBoxTitle(); App.API.ShowMsgBox(errorMsg, errorMsgTitle); } }Add these fields (top of class):
private static int _chefKeysRefCount; private static readonly object _chefKeysSync = new();
🧹 Nitpick comments (5)
Flow.Launcher.Core/Plugin/PluginManager.cs (1)
333-334
: Prefer internal PluginModified for checks within PluginManagerUse the local PluginModified method instead of PublicApi to reduce coupling and avoid unnecessary API hops.
Apply:
- if (PublicApi.Instance.PluginModified(plugin.Metadata.ID)) + if (PluginModified(plugin.Metadata.ID)) return Array.Empty<PluginPair>();Based on learnings
Flow.Launcher/Helper/HotKeyMapper.cs (4)
35-37
: Avoid null service: require Settings from IoCUse GetRequiredService to fail fast instead of risking a null _settings.
Apply:
- _settings = Ioc.Default.GetService<Settings>(); + _settings = Ioc.Default.GetRequiredService<Settings>();
548-564
: Pair change: only stop ChefKeys when no LWin/RWin hotkeys remainMirror the start logic with a guarded stop.
Apply:
- private static void RemoveGlobalHotkeyWithChefKeys(RegisteredHotkeyData hotkeyData) + private static void RemoveGlobalHotkeyWithChefKeys(RegisteredHotkeyData hotkeyData) { var hotkey = hotkeyData.Hotkey; var hotkeyStr = hotkey.ToString(); try { ChefKeysManager.UnregisterHotkey(hotkeyStr); - ChefKeysManager.Stop(); + lock (_chefKeysSync) + { + if (_chefKeysRefCount > 0 && --_chefKeysRefCount == 0) + ChefKeysManager.Stop(); + } } catch (Exception e) { App.API.LogError(ClassName, $"Error removing hotkey: {e.Message} \nStackTrace:{e.StackTrace}"); var errorMsg = string.Format(App.API.GetTranslation("unregisterHotkeyFailed"), hotkeyStr); var errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); App.API.ShowMsgBox(errorMsg, errorMsgTitle); } }
699-705
: Clarify behavior: remove stale TODOThe return is intentional to prevent invoking ActionContext after a plugin handled the hotkey. Drop the TODO to avoid confusion.
Apply:
- // TODO: Remove return to skip other commands if (pluginHotkey.Action.Invoke(selectedResult)) App.API.HideMainWindow(); // Return after invoking the first matching hotkey action so that we will not invoke action context event return;
668-675
: Optional: use PluginManager.PluginModified in HotKeyMapperHotKeyMapper.cs already imports Flow.Launcher.Core.Plugin, so you can call the internal static PluginModified method directly instead of going through App.API for consistency and a small performance gain.
- In Flow.Launcher/Helper/HotKeyMapper.cs line 669, replace
App.API.PluginModified(metadata.ID)
with
PluginManager.PluginModified(metadata.ID)
- In Flow.Launcher/Helper/HotKeyMapper.cs line 694, replace
App.API.PluginModified(metadata.ID)
with
PluginManager.PluginModified(metadata.ID)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
Flow.Launcher.Core/Plugin/PluginManager.cs
(7 hunks)Flow.Launcher.Core/Resource/Internationalization.cs
(1 hunks)Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs
(2 hunks)Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
(1 hunks)Flow.Launcher/Helper/HotKeyMapper.cs
(4 hunks)Flow.Launcher/HotkeyControl.xaml.cs
(3 hunks)Flow.Launcher/Languages/en.xaml
(1 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
(0 hunks)Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs
(0 hunks)Flow.Launcher/ViewModel/MainViewModel.cs
(2 hunks)Plugins/Flow.Launcher.Plugin.Explorer/Views/RenameFile.xaml.cs
(1 hunks)
💤 Files with no reviewable changes (2)
- Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
- Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs
🚧 Files skipped from review as they are similar to previous changes (4)
- Flow.Launcher/HotkeyControl.xaml.cs
- Flow.Launcher.Core/Resource/Internationalization.cs
- Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs
- Flow.Launcher/Languages/en.xaml
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-07-01T05:46:13.251Z
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.
Applied to files:
Flow.Launcher/ViewModel/MainViewModel.cs
Flow.Launcher.Core/Plugin/PluginManager.cs
📚 Learning: 2025-06-24T19:06:48.344Z
Learnt from: Koisu-unavailable
PR: Flow-Launcher/Flow.Launcher#3770
File: Flow.Launcher/ViewModel/MainViewModel.cs:0-0
Timestamp: 2025-06-24T19:06:48.344Z
Learning: In Flow.Launcher's Explorer plugin results, the SubTitle property always contains the directory containing the file. For file results, Title contains the filename and SubTitle contains the parent directory. For directory results, SubTitle contains the directory path itself.
Applied to files:
Flow.Launcher/ViewModel/MainViewModel.cs
📚 Learning: 2025-07-21T09:19:19.012Z
Learnt from: Jack251970
PR: Flow-Launcher/Flow.Launcher#3854
File: Flow.Launcher.Core/Plugin/PluginManager.cs:280-292
Timestamp: 2025-07-21T09:19:19.012Z
Learning: In Flow Launcher's PluginManager.cs, the post-initialization operations (RegisterResultsUpdatedEvent, UpdatePluginMetadataTranslation, RegisterPluginActionKeywords, DialogJump.InitializeDialogJumpPlugin, and AddPluginToLists) are designed to be exception-safe and do not require additional try-catch error handling according to the maintainer Jack251970.
Applied to files:
Flow.Launcher.Core/Plugin/PluginManager.cs
📚 Learning: 2025-03-28T21:12:13.386Z
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.
Applied to files:
Flow.Launcher.Core/Plugin/PluginManager.cs
📚 Learning: 2024-11-03T07:40:11.014Z
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.
Applied to files:
Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
🧬 Code graph analysis (4)
Flow.Launcher/ViewModel/MainViewModel.cs (1)
Flow.Launcher/ViewModel/ResultsViewModel.cs (3)
ResultsViewModel
(16-379)ResultsViewModel
(29-33)ResultsViewModel
(35-52)
Plugins/Flow.Launcher.Plugin.Explorer/Views/RenameFile.xaml.cs (2)
Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs (2)
INotifyPropertyChanged
(9-114)OnDoneButtonClick
(45-77)Plugins/Flow.Launcher.Plugin.Explorer/Helper/RenameThing.cs (3)
RenameThing
(7-109)Rename
(9-54)Rename
(62-108)
Flow.Launcher.Core/Plugin/PluginManager.cs (6)
Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs (5)
PluginsSettings
(7-214)UpdatePluginHotkeyInfo
(96-198)Plugin
(200-207)Plugin
(209-213)Plugin
(216-244)Flow.Launcher.Infrastructure/UserSettings/Settings.cs (1)
Settings
(15-747)Flow.Launcher.Plugin/Interfaces/IPluginHotkey.cs (1)
List
(14-14)Flow.Launcher.Plugin/PluginHotkey.cs (7)
BasePluginHotkey
(11-61)BasePluginHotkey
(17-20)SearchWindowPluginHotkey
(84-97)SearchWindowPluginHotkey
(89-91)GlobalPluginHotkey
(66-79)GlobalPluginHotkey
(71-73)PluginHotkey
(118-134)Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs (1)
ChangePluginHotkey
(106-116)Flow.Launcher/Helper/HotKeyMapper.cs (1)
GlobalPluginHotkey
(663-676)
Flow.Launcher/Helper/HotKeyMapper.cs (4)
Flow.Launcher/ViewModel/MainViewModel.cs (23)
MainViewModel
(31-2301)MainViewModel
(69-204)List
(1317-1339)ReQuery
(373-378)RelayCommand
(339-347)RelayCommand
(349-361)RelayCommand
(363-371)RelayCommand
(380-391)RelayCommand
(393-404)RelayCommand
(406-438)RelayCommand
(440-451)RelayCommand
(453-485)RelayCommand
(487-536)RelayCommand
(570-575)RelayCommand
(577-581)RelayCommand
(583-587)RelayCommand
(589-593)RelayCommand
(595-599)RelayCommand
(601-605)RelayCommand
(607-611)ShouldIgnoreHotkeys
(1836-1839)Result
(1715-1756)Result
(1758-1786)Flow.Launcher.Infrastructure/UserSettings/Settings.cs (2)
Settings
(15-747)Initialize
(25-34)Flow.Launcher.Core/Plugin/PluginManager.cs (8)
PluginManager
(24-986)PluginManager
(168-174)List
(497-524)PluginHotkeyChangedEvent
(966-983)PluginHotkeyChangedEvent
(976-982)ChangePluginHotkey
(613-626)ChangePluginHotkey
(628-664)PluginModified
(764-767)Flow.Launcher.Infrastructure/Hotkey/RegisteredHotkeyData.cs (6)
RegisteredHotkeyData
(88-99)RegisteredHotkeyData
(130-141)RegisteredHotkeyData
(174-187)RegisteredHotkeyData
(221-234)SetHotkey
(240-243)ToString
(246-249)
🔇 Additional comments (4)
Flow.Launcher/ViewModel/MainViewModel.cs (2)
570-575
: Hotkey guard aligns with fullscreen ignore logicGood call wrapping the toggle behind
ShouldIgnoreHotkeys()
so fullscreen/game-mode suppression now applies to this command as well.
1812-1815
: Internal accessor keeps selection plumbing intactReturning the existing
SelectedResults
instance gives the hotkey plumbing what it needs without altering current behavior.Flow.Launcher.Core/Plugin/PluginManager.cs (2)
32-33
: Good change: event over settable delegateSwitching to an event prevents accidental overwrites/nulling and follows .NET conventions. Invocation uses the null-conditional operator correctly.
628-664
: Harden ChangePluginHotkey(SearchWindow): remove dead code and avoid KeyNotFound
- KeyGestureConverter is unused.
- Indexing _windowPluginHotkeys with a missing key throws; guard with TryGetValue.
Apply:
var oldHotkeyStr = settingHotkeyItem.Hotkey; - var converter = new KeyGestureConverter(); var oldHotkey = new HotkeyModel(oldHotkeyStr); var newHotkeyStr = newHotkey.ToString(); // Update hotkey in plugin metadata & setting oldHotkeyItem.Hotkey = newHotkeyStr; settingHotkeyItem.Hotkey = newHotkeyStr; // Update window plugin hotkey dictionary - var oldHotkeyModels = _windowPluginHotkeys[oldHotkey]; - _windowPluginHotkeys[oldHotkey] = oldHotkeyModels.Where(x => x.Item1.ID != plugin.ID || x.Item2.Id != pluginHotkey.Id).ToList(); - if (_windowPluginHotkeys[oldHotkey].Count == 0) - { - _windowPluginHotkeys.Remove(oldHotkey); - } + if (_windowPluginHotkeys.TryGetValue(oldHotkey, out var oldHotkeyModels)) + { + var pruned = oldHotkeyModels + .Where(x => x.Item1.ID != plugin.ID || x.Item2.Id != pluginHotkey.Id) + .ToList(); + if (pruned.Count > 0) + _windowPluginHotkeys[oldHotkey] = pruned; + else + _windowPluginHotkeys.Remove(oldHotkey); + } if (_windowPluginHotkeys.TryGetValue(newHotkey, out var newHotkeyModels)) { var newList = newHotkeyModels.ToList(); newList.Add((plugin, pluginHotkey)); _windowPluginHotkeys[newHotkey] = newList; } else { _windowPluginHotkeys[newHotkey] = new List<(PluginMetadata, SearchWindowPluginHotkey)>() { (plugin, pluginHotkey) }; }
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Context
Windows system has a default context menu for doing some operations to one specific object like exe file, pdf file, etc. And some operations can have some hotkeys like ctrl-c for copy, etc. Since Flow provides many results like them, we should add context menu for them.
Flow designed context menu is good, but currently, for hotkey event binding in context menu, Flow introduces action context (
ActionContext
parameter inAction
andAsyncAction
inResult class
) like ctrl, alt, win key with the enter hotkey event (this is the key to open the action in one result) which means Flow need to regard ctrl+enter key event as enter event so that ctrl key will be passed with enter key.This can lead many possible problems:
Considering these issues, I would like to deprecate the action context API and introduce
IPluginHotkey
interface which can help plugins to register any hotkeys for their results. Additionally, plugins can return results with their supported hotkeys. And we need to find a workaround to ensure the compatibility for action context and I think we can fully deprecate it in future.In future, if plugins can register their hotkeys and specific supported hotkeys for their results. And we can look forward to a command bar like what does as Raycast. It will tell users what commands are available for the selected result. And it looks very nice for me, and I really enjoy this design.
Changes:
IPluginHotkey
to register global & search window hotkeys for one plugins.Hotkey registration refactor for both global hotkeys and main window hotkeys (KeyBinding): Now we are using call back function to register / unregister global and main window hotkeys which can improve code quality (Put all codes related to hotkey in
HotkeyMapper.cs
)Redesign welcome page 3: Removed Ctrl+Enter & Ctrl+Shift+Enter hotkeys since it will be deprated API and added more preset hotkeys.
Resolve #1614.
TODOS:
HotKeyMapper.Initialize();
(Asynchronous Loading & Initialization Plugin Model to Improve Window Startup Speed #3854).Future:
Test: