Skip to content

Commit dad681d

Browse files
committed
Use callback to check plugin hotkey change
1 parent c4fbb3d commit dad681d

File tree

1 file changed

+82
-194
lines changed

1 file changed

+82
-194
lines changed

Flow.Launcher/Helper/HotKeyMapper.cs

Lines changed: 82 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
using Flow.Launcher.Infrastructure.UserSettings;
1414
using Flow.Launcher.Plugin;
1515
using Flow.Launcher.ViewModel;
16-
using NHotkey;
1716
using NHotkey.Wpf;
1817

1918
namespace Flow.Launcher.Helper;
@@ -42,6 +41,7 @@ internal static void Initialize()
4241

4342
_settings.PropertyChanged += Settings_PropertyChanged;
4443
_settings.CustomPluginHotkeys.CollectionChanged += CustomPluginHotkeys_CollectionChanged;
44+
PluginManager.PluginHotkeyChanged += PluginManager_PluginHotkeyChanged;
4545
}
4646

4747
private static void InitializeRegisteredHotkeys()
@@ -127,12 +127,7 @@ private static void InitializeRegisteredHotkeys()
127127
if (hotkey.HotkeyType == HotkeyType.Global && hotkey is GlobalPluginHotkey globalHotkey)
128128
{
129129
var hotkeyStr = metadata.PluginHotkeys.Find(h => h.Id == hotkey.Id)?.Hotkey ?? hotkey.DefaultHotkey;
130-
// TODO: Support removeAction
131-
Action removeHotkeyAction = hotkey.Editable ?
132-
/*() => metadata.PluginHotkeys.RemoveAll(h => h.Id == hotkey.Id) :*/ null:
133-
null;
134-
// TODO: Handle pluginGlobalHotkey & get translation from PluginManager
135-
list.Add(new(RegisteredHotkeyType.PluginGlobalHotkey, HotkeyType.Global, hotkeyStr, "pluginGlobalHotkey", GlobalPluginHotkeyCommand, new GlobalPluginHotkeyPair(metadata, globalHotkey), () => { }));
130+
list.Add(GetRegisteredHotkeyData(new(hotkeyStr), metadata, globalHotkey));
136131
}
137132
}
138133
}
@@ -143,12 +138,7 @@ private static void InitializeRegisteredHotkeys()
143138
{
144139
var hotkeyModel = hotkey.Key;
145140
var windowHotkeys = hotkey.Value;
146-
// TODO: Support removeAction
147-
Action removeHotkeysAction = windowHotkeys.All(h => h.SearchWindowPluginHotkey.Editable) ?
148-
/*() => hotkeyModel.Metadata.PluginWindowHotkeys.RemoveAll(h => h.SearchWindowPluginHotkey.Editable) :*/ null :
149-
null;
150-
// TODO: Handle pluginWindowHotkey & get translation from PluginManager
151-
list.Add(new(RegisteredHotkeyType.PluginWindowHotkey, HotkeyType.SearchWindow, hotkeyModel, "pluginWindowHotkey", WindowPluginHotkeyCommand, new WindowPluginHotkeyPair(windowHotkeys)));
141+
list.Add(GetRegisteredHotkeyData(hotkeyModel, windowHotkeys));
152142
}
153143

154144
// Add registered hotkeys & Set them
@@ -161,6 +151,8 @@ private static void InitializeRegisteredHotkeys()
161151
App.API.LogDebug(ClassName, $"Initialize {_settings.RegisteredHotkeys.Count} hotkeys:\n[\n\t{string.Join(",\n\t", _settings.RegisteredHotkeys)}\n]");
162152
}
163153

154+
#endregion
155+
164156
#region Hotkey Change Events
165157

166158
private static void Settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -267,7 +259,46 @@ private static void CustomPluginHotkeys_CollectionChanged(object sender, NotifyC
267259
}
268260
}
269261

270-
#endregion
262+
private static void PluginManager_PluginHotkeyChanged(PluginManager.PluginHotkeyChangedEvent e)
263+
{
264+
var oldHotkey = e.OldHotkey;
265+
var newHotkey = e.NewHotkey;
266+
var metadata = e.Metadata;
267+
var pluginHotkey = e.PluginHotkey;
268+
269+
if (pluginHotkey is GlobalPluginHotkey globalPluginHotkey)
270+
{
271+
var hotkeyData = SearchRegisteredHotkeyData(metadata, globalPluginHotkey);
272+
RemoveHotkey(hotkeyData);
273+
hotkeyData.Hotkey = newHotkey;
274+
SetHotkey(hotkeyData);
275+
}
276+
else if (pluginHotkey is SearchWindowPluginHotkey)
277+
{
278+
// Search hotkey & Remove registered hotkey data & Unregister hotkeys
279+
var oldHotkeyData = SearchRegisteredHotkeyData(RegisteredHotkeyType.PluginWindowHotkey, oldHotkey);
280+
_settings.RegisteredHotkeys.Remove(oldHotkeyData);
281+
RemoveHotkey(oldHotkeyData);
282+
var newHotkeyData = SearchRegisteredHotkeyData(RegisteredHotkeyType.PluginWindowHotkey, newHotkey);
283+
_settings.RegisteredHotkeys.Remove(newHotkeyData);
284+
RemoveHotkey(newHotkeyData);
285+
286+
// Get hotkey data & Add new registered hotkeys & Register hotkeys
287+
var windowPluginHotkeys = PluginManager.GetWindowPluginHotkeys();
288+
if (windowPluginHotkeys.TryGetValue(oldHotkey, out var oldHotkeyModels))
289+
{
290+
oldHotkeyData = GetRegisteredHotkeyData(oldHotkey, oldHotkeyModels);
291+
_settings.RegisteredHotkeys.Add(oldHotkeyData);
292+
SetHotkey(oldHotkeyData);
293+
}
294+
if (windowPluginHotkeys.TryGetValue(newHotkey, out var newHotkeyModels))
295+
{
296+
newHotkeyData = GetRegisteredHotkeyData(newHotkey, newHotkeyModels);
297+
_settings.RegisteredHotkeys.Add(newHotkeyData);
298+
SetHotkey(newHotkeyData);
299+
}
300+
}
301+
}
271302

272303
#endregion
273304

@@ -280,7 +311,8 @@ private static RegisteredHotkeyData GetRegisteredHotkeyData(CustomPluginHotkey c
280311

281312
private static RegisteredHotkeyData SearchRegisteredHotkeyData(CustomPluginHotkey customPluginHotkey)
282313
{
283-
return _settings.RegisteredHotkeys.FirstOrDefault(h => h.RegisteredType == RegisteredHotkeyType.CustomQuery &&
314+
return _settings.RegisteredHotkeys.FirstOrDefault(h =>
315+
h.RegisteredType == RegisteredHotkeyType.CustomQuery &&
284316
customPluginHotkey.Equals(h.CommandParameter));
285317
}
286318

@@ -297,59 +329,39 @@ private static void ClearHotkeyForCustomQueryHotkey(CustomPluginHotkey customPlu
297329

298330
#endregion
299331

300-
// TODO: Deprecated
301-
private static void SetHotkey(string hotkeyStr, EventHandler<HotkeyEventArgs> action)
332+
#region Plugin Hotkey
333+
334+
private static RegisteredHotkeyData GetRegisteredHotkeyData(HotkeyModel hotkey, PluginMetadata metadata, GlobalPluginHotkey pluginHotkey)
302335
{
303-
var hotkey = new HotkeyModel(hotkeyStr);
304-
SetHotkey(hotkey, action);
336+
Action removeHotkeyAction = pluginHotkey.Editable ?
337+
() => PluginManager.ChangePluginHotkey(metadata, pluginHotkey, HotkeyModel.Empty) : null;
338+
return new(RegisteredHotkeyType.PluginGlobalHotkey, HotkeyType.Global, hotkey, "pluginHotkey", GlobalPluginHotkeyCommand, new GlobalPluginHotkeyPair(metadata, pluginHotkey), removeHotkeyAction);
305339
}
306340

307-
// TODO: Deprecated
308-
private static void SetHotkey(HotkeyModel hotkey, EventHandler<HotkeyEventArgs> action)
341+
private static RegisteredHotkeyData GetRegisteredHotkeyData(HotkeyModel hotkey, List<(PluginMetadata Metadata, SearchWindowPluginHotkey PluginHotkey)> windowHotkeys)
309342
{
310-
if (hotkey.IsEmpty)
311-
{
312-
return;
313-
}
314-
315-
string hotkeyStr = hotkey.ToString();
316-
try
317-
{
318-
HotkeyManager.Current.AddOrReplace(hotkeyStr, hotkey.CharKey, hotkey.ModifierKeys, action);
319-
}
320-
catch (Exception e)
321-
{
322-
App.API.LogError(ClassName,
323-
string.Format("Error registering hotkey {2}: {0} \nStackTrace:{1}",
324-
e.Message,
325-
e.StackTrace,
326-
hotkeyStr));
327-
string errorMsg = string.Format(App.API.GetTranslation("registerHotkeyFailed"), hotkeyStr);
328-
string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle");
329-
App.API.ShowMsgBox(errorMsg, errorMsgTitle);
330-
}
343+
Action removeHotkeysAction = windowHotkeys.All(h => h.PluginHotkey.Editable) ?
344+
() =>
345+
{
346+
foreach (var (metadata, pluginHotkey) in windowHotkeys)
347+
{
348+
PluginManager.ChangePluginHotkey(metadata, pluginHotkey, HotkeyModel.Empty);
349+
}
350+
} : null;
351+
return new(RegisteredHotkeyType.PluginWindowHotkey, HotkeyType.SearchWindow, hotkey, "pluginHotkey", WindowPluginHotkeyCommand, new WindowPluginHotkeyPair(windowHotkeys), removeHotkeysAction);
331352
}
332353

333-
// TODO: Deprecated
334-
internal static void RemoveHotkey(string hotkeyStr)
354+
private static RegisteredHotkeyData SearchRegisteredHotkeyData(PluginMetadata metadata, GlobalPluginHotkey globalPluginHotkey)
335355
{
336-
try
337-
{
338-
if (!string.IsNullOrEmpty(hotkeyStr))
339-
HotkeyManager.Current.Remove(hotkeyStr);
340-
}
341-
catch (Exception e)
342-
{
343-
App.API.LogError(ClassName,
344-
string.Format("Error removing hotkey: {0} \nStackTrace:{1}",
345-
e.Message,
346-
e.StackTrace));
347-
string errorMsg = string.Format(App.API.GetTranslation("unregisterHotkeyFailed"), hotkeyStr);
348-
string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle");
349-
App.API.ShowMsgBox(errorMsg, errorMsgTitle);
350-
}
356+
return _settings.RegisteredHotkeys.FirstOrDefault(h =>
357+
h.RegisteredType == RegisteredHotkeyType.PluginGlobalHotkey &&
358+
h.CommandParameter is GlobalPluginHotkeyPair pair &&
359+
pair.Metadata.ID == metadata.ID &&
360+
pair.GlobalPluginHotkey.Id == globalPluginHotkey.Id);
351361
}
352362

363+
#endregion
364+
353365
#region Hotkey Setting
354366

355367
private static void SetHotkey(RegisteredHotkeyData hotkeyData)
@@ -590,6 +602,17 @@ private static void ChangeRegisteredHotkey(RegisteredHotkeyType registeredType,
590602

591603
#endregion
592604

605+
#region Hotkey Searching
606+
607+
private static RegisteredHotkeyData SearchRegisteredHotkeyData(RegisteredHotkeyType registeredHotkeyType, HotkeyModel hotkeyModel)
608+
{
609+
return _settings.RegisteredHotkeys.FirstOrDefault(h =>
610+
h.RegisteredType == registeredHotkeyType &&
611+
h.Hotkey.Equals(hotkeyModel));
612+
}
613+
614+
#endregion
615+
593616
#region Commands
594617

595618
private static RelayCommand<CustomPluginHotkey> _customQueryHotkeyCommand;
@@ -655,141 +678,6 @@ private static void WindowPluginHotkey(WindowPluginHotkeyPair pair)
655678

656679
#endregion
657680

658-
// TODO: Deprecated
659-
internal static void SetGlobalPluginHotkey(GlobalPluginHotkey globalHotkey, PluginMetadata metadata, string hotkeyStr)
660-
{
661-
var hotkey = new HotkeyModel(hotkeyStr);
662-
SetGlobalPluginHotkey(globalHotkey, metadata, hotkey);
663-
}
664-
665-
// TODO: Deprecated
666-
internal static void SetGlobalPluginHotkey(GlobalPluginHotkey globalHotkey, PluginMetadata metadata, HotkeyModel hotkey)
667-
{
668-
var hotkeyStr = hotkey.ToString();
669-
SetHotkey(hotkeyStr, (s, e) =>
670-
{
671-
if (_mainViewModel.ShouldIgnoreHotkeys() || metadata.Disabled)
672-
return;
673-
674-
globalHotkey.Action?.Invoke();
675-
});
676-
}
677-
678-
// TODO: Deprecated
679-
internal static void SetWindowHotkey(HotkeyModel hotkey, List<(PluginMetadata Metadata, SearchWindowPluginHotkey PluginHotkey)> hotkeyModels)
680-
{
681-
try
682-
{
683-
if (hotkeyModels.Count == 0) return;
684-
if (Application.Current?.MainWindow is MainWindow window)
685-
{
686-
// Cache the command for the hotkey if it already exists
687-
var keyGesture = hotkey.ToKeyGesture();
688-
var existingBinding = window.InputBindings
689-
.OfType<KeyBinding>()
690-
.FirstOrDefault(kb =>
691-
kb.Gesture is KeyGesture keyGesture1 &&
692-
keyGesture.Key == keyGesture1.Key &&
693-
keyGesture.Modifiers == keyGesture1.Modifiers);
694-
if (existingBinding != null)
695-
{
696-
throw new InvalidOperationException($"Key binding {hotkey} already exists");
697-
}
698-
699-
// Create and add the new key binding
700-
var command = BuildCommand(hotkeyModels);
701-
var keyBinding = new KeyBinding(command, keyGesture);
702-
window.InputBindings.Add(keyBinding);
703-
}
704-
}
705-
catch (Exception e)
706-
{
707-
App.API.LogError(ClassName,
708-
string.Format("Error registering window hotkey {2}: {0} \nStackTrace:{1}",
709-
e.Message,
710-
e.StackTrace,
711-
hotkey));
712-
string errorMsg = string.Format(App.API.GetTranslation("registerWindowHotkeyFailed"), hotkey);
713-
string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle");
714-
App.API.ShowMsgBox(errorMsg, errorMsgTitle);
715-
}
716-
}
717-
718-
// TODO: Deprecated
719-
private static ICommand BuildCommand(List<(PluginMetadata Metadata, SearchWindowPluginHotkey PluginHotkey)> hotkeyModels)
720-
{
721-
return new RelayCommand(() =>
722-
{
723-
var selectedResult = _mainViewModel.GetSelectedResults().SelectedItem?.Result;
724-
// Check result nullability
725-
if (selectedResult != null)
726-
{
727-
var pluginId = selectedResult.PluginID;
728-
foreach (var hotkeyModel in hotkeyModels)
729-
{
730-
var metadata = hotkeyModel.Metadata;
731-
var pluginHotkey = hotkeyModel.PluginHotkey;
732-
733-
// Check plugin ID match
734-
if (metadata.ID != pluginId)
735-
continue;
736-
737-
// Check plugin enabled state
738-
if (metadata.Disabled)
739-
continue;
740-
741-
// Check hotkey supported state
742-
if (!selectedResult.HotkeyIds.Contains(pluginHotkey.Id))
743-
continue;
744-
745-
// Check action nullability
746-
if (pluginHotkey.Action == null)
747-
continue;
748-
749-
// TODO: Remove return to skip other commands & Organize main window hotkeys
750-
// Invoke action & return to skip other commands
751-
if (pluginHotkey.Action.Invoke(selectedResult))
752-
App.API.HideMainWindow();
753-
754-
return;
755-
}
756-
}
757-
});
758-
}
759-
760-
// TODO: Deprecated
761-
internal static void RemoveWindowHotkey(HotkeyModel hotkey)
762-
{
763-
try
764-
{
765-
if (Application.Current?.MainWindow is MainWindow window)
766-
{
767-
// Find and remove the key binding with the specified gesture
768-
var keyGesture = hotkey.ToKeyGesture();
769-
var existingBinding = window.InputBindings
770-
.OfType<KeyBinding>()
771-
.FirstOrDefault(kb =>
772-
kb.Gesture is KeyGesture keyGesture1 &&
773-
keyGesture.Key == keyGesture1.Key &&
774-
keyGesture.Modifiers == keyGesture1.Modifiers);
775-
if (existingBinding != null)
776-
{
777-
window.InputBindings.Remove(existingBinding);
778-
}
779-
}
780-
}
781-
catch (Exception e)
782-
{
783-
App.API.LogError(ClassName,
784-
string.Format("Error removing window hotkey: {0} \nStackTrace:{1}",
785-
e.Message,
786-
e.StackTrace));
787-
string errorMsg = string.Format(App.API.GetTranslation("unregisterWindowHotkeyFailed"), hotkey);
788-
string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle");
789-
App.API.ShowMsgBox(errorMsg, errorMsgTitle);
790-
}
791-
}
792-
793681
#region Check Hotkey
794682

795683
internal static bool CheckAvailability(HotkeyModel currentHotkey)

0 commit comments

Comments
 (0)