Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
209 commits
Select commit Hold shift + click to select a range
81d5065
Added function to convert rad to deg and vice versa
Koisu-unavailable Jun 19, 2025
4e03b76
cleanup
Koisu-unavailable Jun 19, 2025
0c34eb0
fix formatting
Koisu-unavailable Jun 19, 2025
762e1c7
Fix Typo
VictoriousRaptor Jun 20, 2025
60e8226
added new action keyword
Koisu-unavailable Jun 20, 2025
8d8388b
Merge branch 'dev' of https://github.com/Koisu-unavailable/Flow.Launc…
Koisu-unavailable Jun 20, 2025
9eb4e64
Revert "Fix Typo"
Koisu-unavailable Jun 20, 2025
3bc06ac
Reapply "Fix Typo"
Koisu-unavailable Jun 20, 2025
c116ea2
added new view
Koisu-unavailable Jun 20, 2025
91e3582
Revert "added new view"
Koisu-unavailable Jun 20, 2025
bfb2adf
Revert "Reapply "Fix Typo""
Koisu-unavailable Jun 20, 2025
670dd1c
added new view
Koisu-unavailable Jun 20, 2025
39366b7
Revert "Revert "added new view""
Koisu-unavailable Jun 20, 2025
459d85d
added new dialogue box for renaming files
Koisu-unavailable Jun 22, 2025
5ae6f97
renaming half-works
Koisu-unavailable Jun 22, 2025
8282304
basic features of renaming files works
Koisu-unavailable Jun 22, 2025
c943982
polishing changes
Koisu-unavailable Jun 22, 2025
502a50b
added keybind to open the renaming dialog
Koisu-unavailable Jun 23, 2025
f36ee61
feat: :sparkles: Added keybind to rename files
Koisu-unavailable Jun 24, 2025
e12c2be
polished ui
Koisu-unavailable Jun 24, 2025
efe6595
revert bad changes
Koisu-unavailable Jun 24, 2025
9f32814
removed unnesscasry stuff
Koisu-unavailable Jun 24, 2025
432f6da
fixed icon in hotkey settings
Koisu-unavailable Jun 24, 2025
657bde5
revert changes to calculator plugin
Koisu-unavailable Jun 24, 2025
8138158
refactoring
Koisu-unavailable Jun 24, 2025
518f883
Changed RenameDialog to modal and added exception logging
Koisu-unavailable Jun 24, 2025
781feeb
added default to RenameFileHotkey
Koisu-unavailable Jun 24, 2025
b0beaaf
formatting
Koisu-unavailable Jun 24, 2025
402d398
checks for reserved names
Koisu-unavailable Jun 24, 2025
b556dac
Refactoring
Koisu-unavailable Jun 24, 2025
a6f1981
removed fragile error handling
Koisu-unavailable Jun 24, 2025
7ae261e
fix typo
Koisu-unavailable Jun 24, 2025
a5ef0cb
fixed unreachable code
Koisu-unavailable Jun 24, 2025
a326a76
refactoring
Koisu-unavailable Jun 24, 2025
54f126a
removed dynamic type
Koisu-unavailable Jun 24, 2025
f991d91
Improved File Rename Feature and Icon Update
onesounds Jun 25, 2025
94f3746
Add plugin hotkey model
Jack251970 Jun 25, 2025
5f49c43
Display plugin hotkey setting
Jack251970 Jun 25, 2025
605837b
Add global key registeration
Jack251970 Jun 25, 2025
f841175
Fix log message issue
Jack251970 Jun 25, 2025
8abd531
Add window key registeration
Jack251970 Jun 25, 2025
4d77bad
Sort hotkey info list
Jack251970 Jun 25, 2025
8ed495d
Improve code quality
Jack251970 Jun 25, 2025
f7fa647
Use IPluginHotkey for explorer plugin
Jack251970 Jun 25, 2025
f2358a5
Fix hotkey control construction issue
Jack251970 Jun 25, 2025
30b9b1f
Add Visible api
Jack251970 Jun 25, 2025
f837b2a
Remove unused using
Jack251970 Jun 25, 2025
35f8ea3
Check hotkey mapper count
Jack251970 Jun 25, 2025
8da182d
Close window when escape pressed
Koisu-unavailable Jun 25, 2025
043bf3b
remove unused using
Koisu-unavailable Jun 25, 2025
0aff9e3
Merge branch 'rename-file' of https://github.com/Koisu-unavailable/Fl…
Jack251970 Jun 26, 2025
53e0bc3
Improve hotkey model
Jack251970 Jun 26, 2025
724b8a7
Support change window hotkey
Jack251970 Jun 26, 2025
c7de03b
Save & restore old command
Jack251970 Jun 26, 2025
b52c7e7
Check result null & Improve docuements
Jack251970 Jun 26, 2025
590ea61
Skip other commands if executed
Jack251970 Jun 26, 2025
ead9b1e
Return to skip other commands
Jack251970 Jun 26, 2025
030a7f3
Adjust margins
Jack251970 Jun 26, 2025
854f808
Use IPluginHotkey for plugin manager plugin
Jack251970 Jun 26, 2025
9f404aa
Use IPluginHotkey for program plugin
Jack251970 Jun 26, 2025
3fe1e50
Resolve context data for uwps
Jack251970 Jun 26, 2025
96b5eb3
Skip this plugin if all hotkeys are invisible
Jack251970 Jun 26, 2025
ddc890e
Skip invisible hotkeys
Jack251970 Jun 26, 2025
e9727c4
Add todo
Jack251970 Jun 26, 2025
95fadcb
Merge branch 'dev' into rename-file
Jack251970 Jun 27, 2025
cda33df
Make constructor protected
Koisu-unavailable Jun 27, 2025
96b3645
Merge branch 'rename-file' of https://github.com/Koisu-unavailable/Fl…
Koisu-unavailable Jun 27, 2025
7fddfd9
Merge branch 'dev' into rename-file
Jack251970 Jun 28, 2025
e087d33
Add hotkey id check
Jack251970 Jun 28, 2025
3b4698e
Use selected results
Jack251970 Jun 28, 2025
e24af14
Add hotkey ids for all results
Jack251970 Jun 28, 2025
73a232f
Fix clone issue
Jack251970 Jun 30, 2025
c9db3ec
Improve string resource
Jack251970 Jun 30, 2025
14310d2
Add code comments
Jack251970 Jul 1, 2025
b87f233
Code quality
Jack251970 Jul 1, 2025
afdb56d
Change RegisteredHotkeys to observable
Jack251970 Jul 2, 2025
1d2aa96
Add property changed for CustomPluginHotkey
Jack251970 Jul 2, 2025
989206b
Add is empty for HotkeyModel
Jack251970 Jul 2, 2025
5910d1d
Add property changed for RegisteredHotkeyData.Hotkey
Jack251970 Jul 2, 2025
2259d74
Add registered type, type, command, command parameter for RegisteredH…
Jack251970 Jul 2, 2025
3231b1d
Implement initialization model for plugin hotkeys
Jack251970 Jul 2, 2025
051af06
Add toggle cmmand for main view model
Jack251970 Jul 2, 2025
20f065a
Remove key bindings which will be registered in hotkey mapper
Jack251970 Jul 2, 2025
d332472
Add todo
Jack251970 Jul 2, 2025
43beef4
Use command & parameter for SetGlobalHotkeyWithChefKeys
Jack251970 Jul 2, 2025
39fa79b
Prepare to deprecation
Jack251970 Jul 2, 2025
6e94d16
Code quality
Jack251970 Jul 2, 2025
f36ca62
Fix typos
Jack251970 Jul 2, 2025
495e2c1
Revert "Add property changed for RegisteredHotkeyData.Hotkey"
Jack251970 Jul 2, 2025
40f1fc6
Allow setter for RegisteredHotkeyData.Hotkey
Jack251970 Jul 2, 2025
f63b8bd
Add ToString
Jack251970 Jul 2, 2025
e41eccc
Add initialization log information
Jack251970 Jul 2, 2025
3b1e014
Add change support for Flow Launcher hotkeys
Jack251970 Jul 2, 2025
2cf6bfb
Prepare for deprecation
Jack251970 Jul 2, 2025
730625c
Remove ChangeHotkey event & Remove deprecated functions
Jack251970 Jul 2, 2025
1c8a8d0
Code quality
Jack251970 Jul 2, 2025
e061f14
Check plugin modified state
Jack251970 Jul 2, 2025
1057f4d
Improve code quality
Jack251970 Jul 2, 2025
d46dedd
Remove Settings.CustomPluginHotkeys null check
Jack251970 Jul 2, 2025
fd3eef4
Add Equals & GetHashCode for CustomPluginHotkey
Jack251970 Jul 2, 2025
96e8eae
Revert "Add property changed for CustomPluginHotkey"
Jack251970 Jul 2, 2025
d0fc344
Explictly implement PropertyChanged
Jack251970 Jul 2, 2025
c4ce8fe
Add check for invalid query shortcuts
Jack251970 Jul 2, 2025
476ad9b
Add constructor for CustomPluginHotkey
Jack251970 Jul 2, 2025
42e2035
Improve string
Jack251970 Jul 2, 2025
ff99669
Refactor custom query hotkey setting window
Jack251970 Jul 2, 2025
5fa3bec
Add hotkey change events for custom query hotkeys
Jack251970 Jul 2, 2025
698fe79
Remove unused removing
Jack251970 Jul 2, 2025
7d0cf1f
Add plugin hotkey type
Jack251970 Jul 2, 2025
805b8ef
No need to check hotkey command when removing
Jack251970 Jul 2, 2025
503bc48
Add empty for hotkey model
Jack251970 Jul 2, 2025
db1c1b2
Use changed event for plugin hotkeys
Jack251970 Jul 2, 2025
c4fbb3d
Check count
Jack251970 Jul 2, 2025
dad681d
Use callback to check plugin hotkey change
Jack251970 Jul 2, 2025
8d26c1c
Add string resource
Jack251970 Jul 2, 2025
cd3eeba
Remove used functions
Jack251970 Jul 2, 2025
11c5b7c
Merge branch 'dev' into rename-file
Jack251970 Jul 2, 2025
e196aa4
Remove todos
Jack251970 Jul 2, 2025
e6fb766
Mark ActionContext as deprecated
Jack251970 Jul 2, 2025
f657494
Workaround for ActionContext compatibility
Jack251970 Jul 2, 2025
2625f6f
Make GetPluginsForInterface private
Jack251970 Jul 3, 2025
089c0fd
Initialize plugin enumerable after all plugins are initialized
Jack251970 Jul 3, 2025
2a52c28
Store plugin hotkey info
Jack251970 Jul 3, 2025
19c5cc3
Merge branch 'dev' into rename-file
Jack251970 Jul 6, 2025
515f24d
Merge branch 'dev' into rename-file
Jack251970 Jul 6, 2025
4874586
Fix build issue
Jack251970 Jul 6, 2025
1948711
Add hotkey get function
Jack251970 Jul 6, 2025
9b92061
Check modified & use IDictionary
Jack251970 Jul 6, 2025
89b454b
Fix typos
Jack251970 Jul 6, 2025
f52ef92
Fix string typos
Jack251970 Jul 6, 2025
5191780
Fix blank line change
Jack251970 Jul 6, 2025
4055e30
Use set hotkey function instead of setter
Jack251970 Jul 6, 2025
a693773
Improve code quality
Jack251970 Jul 6, 2025
d79272a
Cache reversed names
Jack251970 Jul 6, 2025
35474f2
Merge branch 'dev' into rename-file
Jack251970 Jul 7, 2025
9806997
Merge branch 'dev' into rename-file
Jack251970 Jul 10, 2025
c326901
Fix spelling
Jack251970 Jul 10, 2025
e8707ad
Unify error strings
Jack251970 Jul 10, 2025
40ba1ae
Do not validate key gesture for plugin hotkeys
Jack251970 Jul 10, 2025
c2c8a82
Restore plugin hotkey setting if it is not editable anymore
Jack251970 Jul 10, 2025
0dd2f5c
Fix typos
Jack251970 Jul 10, 2025
476d846
Improve code quality
Jack251970 Jul 10, 2025
3dcf22e
Use sorted info
Jack251970 Jul 10, 2025
0077856
Return for exceptions
Jack251970 Jul 10, 2025
ad81a3c
Fix hotkey string issue
Jack251970 Jul 10, 2025
96bf445
Fix action context hotkey event logic
Jack251970 Jul 10, 2025
2febc34
Merge branch 'dev' into rename-file
Jack251970 Jul 12, 2025
633e6d3
Redesign welcome page 3
Jack251970 Jul 12, 2025
b7db22a
Redesign hotkey page
Jack251970 Jul 12, 2025
4ad7ca9
Only use one string
Jack251970 Jul 12, 2025
0d4598b
Add property changed for OpenResultModifiers
Jack251970 Jul 12, 2025
6c21f74
Add Result Modifier Hotkeys changed event
Jack251970 Jul 12, 2025
28bd07d
Improve code quality
Jack251970 Jul 12, 2025
64cf1ed
Fix IsActionContextEvent logic
Jack251970 Jul 12, 2025
ada2af8
Fix open result command parameter issue
Jack251970 Jul 12, 2025
2acf9b4
Merge branch 'dev' into rename-file
Jack251970 Jul 14, 2025
98179eb
Merge branch 'dev' into rename-file
Jack251970 Jul 15, 2025
15e4a4f
Merge branch 'dev' into rename-file
Jack251970 Jul 19, 2025
45ed9fa
Merge branch 'dev' into rename-file
Jack251970 Jul 20, 2025
11e8a58
Add dialog jump hotkey
Jack251970 Jul 20, 2025
2ce4157
Fix build issue
Jack251970 Jul 20, 2025
2f71d0d
Fix key duplication
Jack251970 Jul 20, 2025
adb1adb
Do not execute when dialog jump is disabled
Jack251970 Jul 20, 2025
b88e2e9
Do not register dialog jump hotkey when dialog jump is disabled
Jack251970 Jul 20, 2025
912d5dd
Merge branch 'dev' into rename-file
Jack251970 Jul 24, 2025
d8d42b8
Merge branch 'dev' into rename-file
Jack251970 Jul 27, 2025
98816ac
Fix build issue
Jack251970 Jul 27, 2025
11dbce6
Merge branch 'dev' into rename-file
Jack251970 Aug 30, 2025
b84c6ec
Use an event, not a settable delegate property, for PluginHotkeyChanged
Jack251970 Aug 30, 2025
007c089
Merge branch 'rename-file' of https://github.com/Koisu-unavailable/Fl…
Jack251970 Aug 30, 2025
d8198d0
Add a null/invalid ContextData guard in hotkey Action
Jack251970 Aug 30, 2025
9733da7
Merge branch 'dev' into rename-file
Jack251970 Sep 5, 2025
88e1300
Merge branch 'dev' into rename-file
Jack251970 Sep 6, 2025
542d1eb
Merge branch 'dev' into rename-file
Jack251970 Sep 21, 2025
622a3ab
Resolve conflicts
Jack251970 Sep 21, 2025
e98f790
Merge branch 'dev' into rename-file
Jack251970 Sep 21, 2025
0b7c040
Null check order bug can throw NRE
Jack251970 Sep 21, 2025
785d149
Guard selection logic to avoid ArgumentOutOfRangeException when base …
Jack251970 Sep 21, 2025
06dc688
Fix build issue & Improve code quality
Jack251970 Sep 21, 2025
83c2edf
Merge branch 'dev' into rename-file
Jack251970 Sep 28, 2025
e206f4f
Fix build issue
Jack251970 Sep 28, 2025
93d9667
Reject blank directory names
Jack251970 Sep 28, 2025
0dd2f05
Add code comments & Use Flow.Launcher.Localization to improve code qu…
Jack251970 Sep 28, 2025
970ed26
Merge branch 'rename-file' of https://github.com/Koisu-unavailable/Fl…
Jack251970 Sep 28, 2025
5d2fb6e
Add code comments
Jack251970 Sep 28, 2025
5c4c802
Merge branch 'dev' into rename-file
Jack251970 Oct 5, 2025
d36b8b2
Resolve conflicts for WelcomePage3
Jack251970 Oct 5, 2025
a64bed3
Resolve conflicts in SettingsPaneHotkey.xaml.cs
Jack251970 Oct 5, 2025
8e7261d
Resolve conflicts in SettingsPaneHotkey.xaml
Jack251970 Oct 5, 2025
f5e5fe5
Fix UI error
Jack251970 Oct 5, 2025
cb6b0a0
Add async plugin icon loading to SettingsExpander
Jack251970 Oct 5, 2025
e2ccbe5
Merge branch 'dev' into rename-file
Jack251970 Oct 14, 2025
7859db0
Resolve conflicts
Jack251970 Oct 14, 2025
922feb4
Merge branch 'dev' into rename-file
Jack251970 Oct 14, 2025
8e71130
Merge branch 'dev' into rename-file
Jack251970 Oct 16, 2025
79b0385
Refactor plugin hotkey and action keyword management
Jack251970 Oct 16, 2025
fe31632
Fix typos
Jack251970 Oct 16, 2025
62cca42
Improve code comments
Jack251970 Oct 16, 2025
c30cd7c
Fix typos
Jack251970 Oct 16, 2025
af5950b
Improve code comments
Jack251970 Oct 16, 2025
f6759a5
Fix typos
Jack251970 Oct 16, 2025
e3306ec
Add conditional check for plugin hotkey updates
Jack251970 Oct 16, 2025
6d2be7a
Fix typos
Jack251970 Oct 16, 2025
d8a4bbc
Fix null handling to prevent NullReferenceException
Jack251970 Oct 16, 2025
8c95ddc
Add plugin to _hotkeyPlugins collection for tracking
Jack251970 Oct 16, 2025
dccdd95
Improve code comments
Jack251970 Oct 16, 2025
811239b
Refactor hotkey handling and improve thread safety
Jack251970 Oct 16, 2025
f8e588b
Refactor: Remove unused namespaces and hotkey converter
Jack251970 Oct 16, 2025
522ff15
Refactor hotkey initialization logic
Jack251970 Oct 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 202 additions & 0 deletions Flow.Launcher.Core/Plugin/PluginManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.DialogJump;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
Expand All @@ -31,14 +32,22 @@ public static class PluginManager
private static readonly ConcurrentDictionary<string, PluginPair> _globalPlugins = [];
private static readonly ConcurrentDictionary<string, PluginPair> _nonGlobalPlugins = [];

public static event Action<PluginHotkeyChangedEvent> PluginHotkeyChanged;
public static event Action<PluginPair> PluginHotkeyInitialized;

private static PluginsSettings Settings;
private static readonly ConcurrentBag<string> ModifiedPlugins = [];

private static readonly ConcurrentBag<PluginPair> _contextMenuPlugins = [];
private static readonly ConcurrentBag<PluginPair> _homePlugins = [];
private static readonly ConcurrentBag<PluginPair> _translationPlugins = [];
private static readonly ConcurrentBag<PluginPair> _hotkeyPlugins = [];
private static readonly ConcurrentBag<PluginPair> _externalPreviewPlugins = [];

private static readonly Lock _pluginHotkeyInfoUpdateLock = new();
private static readonly ConcurrentDictionary<PluginPair, List<BasePluginHotkey>> _pluginHotkeyInfo = [];
private static readonly ConcurrentDictionary<HotkeyModel, ConcurrentBag<(PluginMetadata, SearchWindowPluginHotkey)>> _windowPluginHotkeys = [];

/// <summary>
/// Directories that will hold Flow Launcher plugin directory
/// </summary>
Expand Down Expand Up @@ -302,6 +311,9 @@ public static async Task InitializePluginsAsync(IResultUpdateRegister register)
// Add plugin to Dialog Jump plugin list after the plugin is initialized
DialogJump.InitializeDialogJumpPlugin(pair);

// Check and initialize plugin hotkeys after the plugin is initialized
CheckPluginHotkeys(pair);

// Add plugin to lists after the plugin is initialized
AddPluginToLists(pair);
}));
Expand Down Expand Up @@ -359,6 +371,22 @@ private static void AddPluginToLists(PluginPair pair)
_allInitializedPlugins.TryAdd(pair.Metadata.ID, pair);
}

private static void CheckPluginHotkeys(PluginPair pair)
{
if (pair.Plugin is IPluginHotkey)
{
InitializePluginHotkeyInfo(pair);
// Since settings cannot be changed concurrently, we must use a lock here
lock (_pluginHotkeyInfoUpdateLock)
{
Settings.UpdatePluginHotkeyInfo(GetPluginHotkeyInfo(pair.Metadata.ID));
}
InitializeWindowPluginHotkey(pair);
_hotkeyPlugins.Add(pair);
PluginHotkeyInitialized?.Invoke(pair);
}
}

#endregion

#region Validate & Query Plugins
Expand Down Expand Up @@ -586,6 +614,11 @@ public static List<PluginPair> GetTranslationPlugins()
return [.. _translationPlugins.Where(p => !PluginModified(p.Metadata.ID))];
}

public static List<PluginPair> GetHotkeyPlugins()
{
return [.. _hotkeyPlugins.Where(p => !PluginModified(p.Metadata.ID))];
}

#endregion

#region Update Metadata & Get Plugin
Expand Down Expand Up @@ -791,6 +824,175 @@ public static void RemoveActionKeyword(string id, string oldActionkeyword)

#endregion

#region Plugin Hotkey

private static void InitializePluginHotkeyInfo(PluginPair pair)
{
var plugin = (IPluginHotkey)pair.Plugin;
var hotkeys = plugin.GetPluginHotkeys();
_pluginHotkeyInfo.TryAdd(pair, hotkeys);
}

private static void InitializeWindowPluginHotkey(PluginPair pair)
{
foreach (var info in GetPluginHotkeyInfo(pair.Metadata.ID))
{
var pluginPair = info.Key;
var hotkeyInfo = info.Value;
var metadata = pluginPair.Metadata;
foreach (var hotkey in hotkeyInfo)
{
if (hotkey.HotkeyType == HotkeyType.SearchWindow && hotkey is SearchWindowPluginHotkey searchWindowHotkey)
{
var hotkeySetting = metadata.PluginHotkeys.Find(h => h.Id == hotkey.Id)?.Hotkey ?? hotkey.DefaultHotkey;
var hotkeyModel = new HotkeyModel(hotkeySetting);
if (!_windowPluginHotkeys.TryGetValue(hotkeyModel, out var list))
{
list = [];
_windowPluginHotkeys[hotkeyModel] = list;
}
list.Add((pluginPair.Metadata, searchWindowHotkey));
}
}
}
}

public static Dictionary<PluginPair, List<BasePluginHotkey>> GetPluginHotkeyInfo(string id = null)
{
if (id == null)
{
// Return all plugin hotkey info except those from modified plugins
return _pluginHotkeyInfo.Where(p => !PluginModified(p.Key.Metadata.ID))
.ToDictionary(p => p.Key, p => p.Value);
}
else
{
// Return plugin hotkey info for specified plugin id
return _pluginHotkeyInfo.Where(p => p.Key.Metadata.ID == id)
.ToDictionary(p => p.Key, p => p.Value);
}
}

public static Dictionary<HotkeyModel, ConcurrentBag<(PluginMetadata Metadata, SearchWindowPluginHotkey SearchWindowPluginHotkey)>> GetWindowPluginHotkeys(string id = null)
{
// Here we do not need to check PluginModified since we will check it in hotkey events
if (id == null)
{
// Return all window plugin hotkeys
return _windowPluginHotkeys.ToDictionary(p => p.Key, p => p.Value);
}
else
{
// Return window plugin hotkeys for specified plugin id
// If one HotkeyModel is already included by other plugins, it will be removed so that HotkeyMapper will not register this Window hotkey duplicately
var windowPluginHotkeys = new Dictionary<HotkeyModel, ConcurrentBag<(PluginMetadata Metadata, SearchWindowPluginHotkey SearchWindowPluginHotkey)>>();
foreach (var key in _windowPluginHotkeys)
{
// Check if all items in the list are from the specified plugin
if (key.Value.All(x => x.Item1.ID == id))
{
// We must use the reference of this ConcurrentBag so that it can be updated in the next
windowPluginHotkeys[key.Key] = key.Value;
}
}
return windowPluginHotkeys;
}
}

public static void UpdatePluginHotkeyInfoTranslations(PluginPair pair)
{
var newHotkeys = ((IPluginHotkey)pair.Plugin).GetPluginHotkeys();
if (_pluginHotkeyInfo.TryGetValue(pair, out var oldHotkeys))
{
foreach (var newHotkey in newHotkeys)
{
if (oldHotkeys.FirstOrDefault(h => h.Id == newHotkey.Id) is BasePluginHotkey pluginHotkey)
{
pluginHotkey.Name = newHotkey.Name;
pluginHotkey.Description = newHotkey.Description;
}
else
{
oldHotkeys.Add(newHotkey);
}
}
}
else
{
_pluginHotkeyInfo.TryAdd(pair, newHotkeys);
}
}

public static void ChangePluginHotkey(PluginMetadata plugin, GlobalPluginHotkey pluginHotkey, HotkeyModel newHotkey)
{
var oldHotkeyItem = plugin.PluginHotkeys.First(h => h.Id == pluginHotkey.Id);
var settingHotkeyItem = Settings.GetPluginSettings(plugin.ID).pluginHotkeys.First(h => h.Id == pluginHotkey.Id);
var oldHotkeyStr = settingHotkeyItem.Hotkey;
var oldHotkey = new HotkeyModel(oldHotkeyStr);
var newHotkeyStr = newHotkey.ToString();

// Update hotkey in plugin metadata & setting
oldHotkeyItem.Hotkey = newHotkeyStr;
settingHotkeyItem.Hotkey = newHotkeyStr;

PluginHotkeyChanged?.Invoke(new PluginHotkeyChangedEvent(oldHotkey, newHotkey, plugin, pluginHotkey));
}

public static void ChangePluginHotkey(PluginMetadata plugin, SearchWindowPluginHotkey pluginHotkey, HotkeyModel newHotkey)
{
var oldHotkeyItem = plugin.PluginHotkeys.First(h => h.Id == pluginHotkey.Id);
var settingHotkeyItem = Settings.GetPluginSettings(plugin.ID).pluginHotkeys.First(h => h.Id == pluginHotkey.Id);
var oldHotkeyStr = settingHotkeyItem.Hotkey;
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)];
if (_windowPluginHotkeys[oldHotkey].IsEmpty)
{
_windowPluginHotkeys.TryRemove(oldHotkey, out var _);
}

if (_windowPluginHotkeys.TryGetValue(newHotkey, out var newHotkeyModels))
{
var newList = newHotkeyModels.ToList();
newList.Add((plugin, pluginHotkey));
_windowPluginHotkeys[newHotkey] = [.. newList];
}
else
{
_windowPluginHotkeys[newHotkey] =
[
(plugin, pluginHotkey)
];
}

PluginHotkeyChanged?.Invoke(new PluginHotkeyChangedEvent(oldHotkey, newHotkey, plugin, pluginHotkey));
}

#region Class

public class PluginHotkeyChangedEvent(HotkeyModel oldHotkey, HotkeyModel newHotkey,
PluginMetadata metadata, BasePluginHotkey pluginHotkey)
{
public HotkeyModel NewHotkey { get; } = newHotkey;

public HotkeyModel OldHotkey { get; } = oldHotkey;

public PluginMetadata Metadata { get; } = metadata;

public BasePluginHotkey PluginHotkey { get; } = pluginHotkey;
}

#endregion

#endregion

#region Plugin Install & Uninstall & Update

#region Private Functions
Expand Down
10 changes: 10 additions & 0 deletions Flow.Launcher.Core/Resource/Internationalization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ public static void UpdatePluginMetadataTranslations()
{
p.Metadata.Name = pluginI18N.GetTranslatedPluginTitle();
p.Metadata.Description = pluginI18N.GetTranslatedPluginDescription();
if (p.Plugin is IPluginHotkey)
{
// Update plugin hotkey name & description
PluginManager.UpdatePluginHotkeyInfoTranslations(p);
}
pluginI18N.OnCultureInfoChanged(CultureInfo.CurrentCulture);
}
catch (Exception e)
Expand All @@ -385,6 +390,11 @@ public static void UpdatePluginMetadataTranslation(PluginPair p)
{
p.Metadata.Name = pluginI18N.GetTranslatedPluginTitle();
p.Metadata.Description = pluginI18N.GetTranslatedPluginDescription();
if (p.Plugin is IPluginHotkey)
{
// Update plugin hotkey name & description
PluginManager.UpdatePluginHotkeyInfoTranslations(p);
}
pluginI18N.OnCultureInfoChanged(CultureInfo.CurrentCulture);
}
catch (Exception e)
Expand Down
13 changes: 9 additions & 4 deletions Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.Mvvm.Input;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.DialogJump.Models;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using NHotkey;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.Accessibility;
using System.Collections.Concurrent;

namespace Flow.Launcher.Infrastructure.DialogJump
{
Expand Down Expand Up @@ -173,22 +173,22 @@
}
if (!_locationChangeHook.IsNull)
{
PInvoke.UnhookWinEvent(_locationChangeHook);

Check warning on line 176 in Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`PInvoke` is not a recognized word. (unrecognized-spelling)
_locationChangeHook = HWINEVENTHOOK.Null;
}
if (!_destroyChangeHook.IsNull)
{
PInvoke.UnhookWinEvent(_destroyChangeHook);

Check warning on line 181 in Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`PInvoke` is not a recognized word. (unrecognized-spelling)
_destroyChangeHook = HWINEVENTHOOK.Null;
}
if (!_hideChangeHook.IsNull)
{
PInvoke.UnhookWinEvent(_hideChangeHook);

Check warning on line 186 in Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`PInvoke` is not a recognized word. (unrecognized-spelling)
_hideChangeHook = HWINEVENTHOOK.Null;
}
if (!_dialogEndChangeHook.IsNull)
{
PInvoke.UnhookWinEvent(_dialogEndChangeHook);

Check warning on line 191 in Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`PInvoke` is not a recognized word. (unrecognized-spelling)
_dialogEndChangeHook = HWINEVENTHOOK.Null;
}

Expand Down Expand Up @@ -329,7 +329,7 @@
if (PublicApi.Instance.PluginModified(explorer.Metadata.ID) || // Plugin is modified
explorer.Metadata.Disabled) continue; // Plugin is disabled

var explorerWindow = explorer.Plugin.CheckExplorerWindow(hWnd);

Check warning on line 332 in Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`Wnd` is not a recognized word. (unrecognized-spelling)
if (explorerWindow != null)
{
_dialogJumpExplorers[explorer] = explorerWindow;
Expand Down Expand Up @@ -464,10 +464,15 @@

#endregion

#region Hotkey
#region Hotkey Command

public static void OnToggleHotkey(object sender, HotkeyEventArgs args)
private static RelayCommand _dialogJumpCommand;
public static IRelayCommand DialogJumpCommand => _dialogJumpCommand ??= new RelayCommand(OnToggleHotkey);

private static void OnToggleHotkey()
{
if (!_settings.EnableDialogJump) return;

_ = Task.Run(async () =>
{
try
Expand Down
24 changes: 19 additions & 5 deletions Flow.Launcher.Infrastructure/Hotkey/HotkeyModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
}
}

public readonly bool IsEmpty => CharKey == Key.None && !Alt && !Shift && !Win && !Ctrl;

public static HotkeyModel Empty => new();

public HotkeyModel(string hotkeyString)
{
Parse(hotkeyString);
Expand Down Expand Up @@ -117,12 +121,22 @@
}
}

public override string ToString()
public bool Equals(HotkeyModel other)
{
return CharKey == other.CharKey && ModifierKeys == other.ModifierKeys;
}

public KeyGesture ToKeyGesture()
{
return new KeyGesture(CharKey, ModifierKeys);
}

public override readonly string ToString()
{
return string.Join(" + ", EnumerateDisplayKeys());
}

public IEnumerable<string> EnumerateDisplayKeys()
public readonly IEnumerable<string> EnumerateDisplayKeys()
{
if (Ctrl && CharKey is not (Key.LeftCtrl or Key.RightCtrl))
{
Expand Down Expand Up @@ -155,9 +169,9 @@
/// <summary>
/// Validate hotkey
/// </summary>
/// <param name="validateKeyGestrue">Try to validate hotkey as a KeyGesture.</param>
/// <param name="validateKeyGesture">Try to validate hotkey as a KeyGesture.</param>
/// <returns></returns>
public bool Validate(bool validateKeyGestrue = false)
public bool Validate(bool validateKeyGesture = false)
{
switch (CharKey)
{
Expand All @@ -167,12 +181,12 @@
case Key.RightCtrl:
case Key.LeftShift:
case Key.RightShift:
case Key.LWin:

Check warning on line 184 in Flow.Launcher.Infrastructure/Hotkey/HotkeyModel.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`LWin` is not a recognized word. (unrecognized-spelling)
case Key.RWin:
case Key.None:
return false;
default:
if (validateKeyGestrue)
if (validateKeyGesture)
{
try
{
Expand Down
4 changes: 2 additions & 2 deletions Flow.Launcher.Infrastructure/Hotkey/IHotkeySettings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace Flow.Launcher.Infrastructure.Hotkey;

Expand All @@ -13,5 +13,5 @@ public interface IHotkeySettings
/// A list of hotkeys that have already been registered. The dialog will display these hotkeys and provide a way to
/// unregister them.
/// </summary>
public List<RegisteredHotkeyData> RegisteredHotkeys { get; }
public ObservableCollection<RegisteredHotkeyData> RegisteredHotkeys { get; }
}
Loading
Loading