Skip to content

Conversation

Koisu-unavailable
Copy link

@Koisu-unavailable Koisu-unavailable commented Jun 24, 2025

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 in Action and AsyncAction in Result 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:

  1. Code quality issue: All events will be put in one action delegate with if sentences to check the action context.
  2. Window hotkey binding complexity: Flow needs to bind many preset hotkeys like ctrl-enter which can lead to complexity to hotkey management.
  3. Plugin hotkey registration difficulty: Plugin can only register hotkeys to one results with enter key, and it cannot register other hotkeys like F2 or something else.
  4. Plugin result confusion: Using alt+enter or ctrl+enter will trigger enter event for those results without specific handler for action context.

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:

  • New Interface IPluginHotkey to register global & search window hotkeys for one plugins.
/// <summary>
/// Represent plugins that support global hotkey or search window hotkey.
/// </summary>
public interface IPluginHotkey : IFeatures
{
    /// <summary>
    /// Get the list of plugin hotkeys which will be registered in the settings page.
    /// </summary>
    /// <returns></returns>
    List<BasePluginHotkey> GetPuginHotkeys();
}
  • Plugin hotkey setting UI
image
  • Add an item to the context menu for the explorer plugin that allow you to rename files/directories. It opens a dialog.
image
  • Add a hotkey (defaults to F2) that also opens the dialog when a file is selected
image
  • 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.

image
  • Redesign hotkey page: Removed Ctrl+Enter & Ctrl+Shift+Enter hotkeys since it will be deprated API and added all Flow hotkeys.
image

Resolve #1614.

TODOS:

Future:

  • Command bar like Raycast with those commands (Not sure, need discussion)

Test:

  • Welcome page hotkey can be changed.
  • All preset hotkeys in Hotkey page can be changed.
  • Result modifier can work.
  • Custom Query Hotkey can be added, deleted and edited.
  • Plugin global and window hotkey can be registered and edited.
  • Original API ActionContext can work.
  • Dialog Jump hotkey can be changed / enabled / disabled.

@Koisu-unavailable Koisu-unavailable marked this pull request as ready for review June 24, 2025 03:59
Copy link

gitstream-cm bot commented Jun 24, 2025

🥷 Code experts: Jack251970, onesounds

Jack251970, onesounds have most 👩‍💻 activity in the files.
Jack251970, onesounds have most 🧠 knowledge in the files.

See details

Flow.Launcher.Infrastructure/UserSettings/Settings.cs

Activity based on git-commit:

Jack251970 onesounds
JUN 3 additions & 2 deletions
MAY 84 additions & 30 deletions 5 additions & 3 deletions
APR 34 additions & 83 deletions 104 additions & 38 deletions
MAR 142 additions & 94 deletions 10 additions & 0 deletions
FEB 10 additions & 4 deletions
JAN 17 additions & 4 deletions

Knowledge based on git-blame:
Jack251970: 31%
onesounds: 20%

Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs

Activity based on git-commit:

Jack251970 onesounds
JUN 45 additions & 2 deletions
MAY 4 additions & 1 deletions 5 additions & 0 deletions
APR 228 additions & 27 deletions
MAR
FEB 38 additions & 28 deletions
JAN 21 additions & 3 deletions

Knowledge based on git-blame:
Jack251970: 50%
onesounds: 1%

Flow.Launcher/HotkeyControl.xaml.cs

Activity based on git-commit:

Jack251970 onesounds
JUN
MAY 5 additions & 0 deletions
APR 11 additions & 15 deletions 3 additions & 0 deletions
MAR 150 additions & 37 deletions
FEB
JAN

Knowledge based on git-blame:
Jack251970: 44%
onesounds: 2%

Flow.Launcher/Languages/en.xaml

Activity based on git-commit:

Jack251970 onesounds
JUN 8 additions & 0 deletions 7 additions & 6 deletions
MAY 14 additions & 3 deletions 15 additions & 2 deletions
APR 22 additions & 21 deletions 45 additions & 23 deletions
MAR 67 additions & 42 deletions 8 additions & 3 deletions
FEB 15 additions & 9 deletions
JAN 1 additions & 0 deletions

Knowledge based on git-blame:
onesounds: 43%
Jack251970: 12%

Flow.Launcher/MainWindow.xaml

Activity based on git-commit:

Jack251970 onesounds
JUN
MAY 3 additions & 3 deletions 4 additions & 4 deletions
APR
MAR 42 additions & 26 deletions
FEB 1 additions & 1 deletions
JAN

Knowledge based on git-blame:
onesounds: 85%
Jack251970: 7%

Flow.Launcher/PublicAPIInstance.cs

Activity based on git-commit:

Jack251970 onesounds
JUN 54 additions & 22 deletions
MAY 124 additions & 131 deletions 190 additions & 74 deletions
APR 165 additions & 61 deletions
MAR 21 additions & 19 deletions
FEB 28 additions & 11 deletions
JAN 45 additions & 47 deletions

Knowledge based on git-blame:
Jack251970: 53%
onesounds: 8%

Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml

Activity based on git-commit:

Jack251970 onesounds
JUN
MAY 1 additions & 1 deletions 4 additions & 1 deletions
APR
MAR 14 additions & 28 deletions
FEB
JAN

Knowledge based on git-blame:
onesounds: 11%
Jack251970: 3%

Flow.Launcher/ViewModel/MainViewModel.cs

Activity based on git-commit:

Jack251970 onesounds
JUN 25 additions & 13 deletions
MAY 529 additions & 316 deletions 4 additions & 0 deletions
APR 35 additions & 28 deletions
MAR 695 additions & 628 deletions 293 additions & 201 deletions
FEB 63 additions & 21 deletions 23 additions & 25 deletions
JAN 17 additions & 21 deletions

Knowledge based on git-blame:
Jack251970: 41%
onesounds: 9%

Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs

Activity based on git-commit:

Jack251970 onesounds
JUN
MAY 23 additions & 0 deletions 3 additions & 3 deletions
APR 13 additions & 18 deletions
MAR
FEB
JAN 1 additions & 0 deletions

Knowledge based on git-blame:
Jack251970: 7%
onesounds: 4%

Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml

Activity based on git-commit:

Jack251970 onesounds
JUN 7 additions & 0 deletions 5 additions & 2 deletions
MAY 10 additions & 2 deletions
APR
MAR
FEB
JAN

Knowledge based on git-blame:
onesounds: 17%
Jack251970: 9%

Plugins/Flow.Launcher.Plugin.Explorer/Main.cs

Activity based on git-commit:

Jack251970 onesounds
JUN 4 additions & 4 deletions
MAY 0 additions & 1 deletions
APR
MAR
FEB
JAN

Knowledge based on git-blame:
Jack251970: 4%

To learn more about /:\ gitStream - Visit our Docs

This comment has been minimized.

@jjw24
Copy link
Member

jjw24 commented Aug 30, 2025

Please resolve conflict.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 consistency

Tighten 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 naming

Elsewhere 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 idempotence

If 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 hardening

Apply 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.

📥 Commits

Reviewing files that changed from the base of the PR and between b88e2e9 and 11dbce6.

📒 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 good

Implementing IPluginHotkey here is consistent with the new hotkey architecture.

Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml (4)

134-141: History hotkey change LGTM

Switch to “OpenHistoryHotkey” with Ctrl+H looks consistent.


152-157: Reload plugin hotkey as non-editable F5

Reasonable choice. Please verify this doesn’t collide with any in-window refresh actions.


159-169: New first/last result presets LGTM

Clear, non-conflicting keys.


207-223: Requery/GameMode/CopyPath presets LGTM

Static displays are fine given recent preset policy.

Flow.Launcher.Core/Plugin/PluginManager.cs (4)

289-292: Order and initialization LGTM

Hotkey info init → settings sync → window mapping is a sane sequence.


556-561: Return a defensive copy LGTM

Returning a copy of _windowPluginHotkeys avoids external mutation.


973-994: Event payload class LGTM

Shape 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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 results

Id 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 behavior

On 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 HotkeyIds

Define 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

📥 Commits

Reviewing files that changed from the base of the PR and between 11dbce6 and 88e1300.

📒 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 HotkeyIds

System.Collections.Generic is required for the new HotkeyIds lists.


309-316: Public wrappers for OpenFile/OpenFolder are appropriate

Making these public supports plugin hotkey actions and centralizes Everything run-count updates and messaging. Looks good.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📥 Commits

Reviewing files that changed from the base of the PR and between 88e1300 and 542d1eb.

📒 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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 keep Rename 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

📥 Commits

Reviewing files that changed from the base of the PR and between 542d1eb and e98f790.

📒 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 load

Fixes 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

Jack251970 and others added 4 commits September 21, 2025 21:49
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>
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 remain

Stopping 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 PluginManager

Use 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 IoC

Use 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 remain

Mirror 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 TODO

The 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 HotKeyMapper

HotKeyMapper.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

📥 Commits

Reviewing files that changed from the base of the PR and between 0b7c040 and 83c2edf.

📒 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 logic

Good 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 intact

Returning 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 delegate

Switching 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)
             };
         }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Let the user select a file/folder from search result and edit its name directly inside Flow; preferably by pressing F2.
6 participants