diff --git a/Source/LibationAvalonia/Controls/DataGridContextMenus.cs b/Source/LibationAvalonia/Controls/DataGridContextMenus.cs index 2bddde98..22187a2a 100644 --- a/Source/LibationAvalonia/Controls/DataGridContextMenus.cs +++ b/Source/LibationAvalonia/Controls/DataGridContextMenus.cs @@ -1,4 +1,4 @@ -using Avalonia.Collections; +using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Input; using System; @@ -105,7 +105,7 @@ public class DataGridCellContextMenu where TContext : class private static KeyEventArgs GetCopyEventArgs() => new() { Key = Key.C, - KeyModifiers = KeyModifiers.Control, + KeyModifiers = KeyGestureHelper.CommandModifier, Route = Avalonia.Interactivity.RoutingStrategies.Bubble, PhysicalKey = PhysicalKey.C, KeySymbol = "c", diff --git a/Source/LibationAvalonia/KeyGestureHelper.cs b/Source/LibationAvalonia/KeyGestureHelper.cs new file mode 100644 index 00000000..192737d0 --- /dev/null +++ b/Source/LibationAvalonia/KeyGestureHelper.cs @@ -0,0 +1,14 @@ +using Avalonia.Input; +using LibationFileManager; + +namespace LibationAvalonia; + +/// Cross-platform keyboard modifier helpers. Use these instead of hardcoding Control/Alt/Meta per OS. +public static class KeyGestureHelper +{ + /// Primary "command" modifier: Control on Windows/Linux, Meta (Command) on macOS. + public static KeyModifiers CommandModifier => Configuration.IsMacOs ? KeyModifiers.Meta : KeyModifiers.Control; + + /// Menu accelerator modifier that works on all platforms: Alt on Windows/Linux, Meta on macOS. Use (Alt|Meta) so one binding accepts either. + public static KeyModifiers MenuModifier => KeyModifiers.Alt | KeyModifiers.Meta; +} diff --git a/Source/LibationAvalonia/ViewModels/MainVM.Filters.cs b/Source/LibationAvalonia/ViewModels/MainVM.Filters.cs index eb0a1c79..33a69d28 100644 --- a/Source/LibationAvalonia/ViewModels/MainVM.Filters.cs +++ b/Source/LibationAvalonia/ViewModels/MainVM.Filters.cs @@ -1,4 +1,4 @@ -using Avalonia; +using Avalonia; using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Data; @@ -114,7 +114,7 @@ partial class MainVM { //Register hotkeys Command + 1 - 0 for quick filters var key = index == 10 ? Key.D0 : Key.D0 + index; - nativeMenuItem.Gesture = new KeyGesture(key, KeyModifiers.Meta); + nativeMenuItem.Gesture = new KeyGesture(key, KeyGestureHelper.CommandModifier); } else if (!Configuration.IsMacOs && index <= 12) { diff --git a/Source/LibationAvalonia/ViewModels/MainVM.Import.cs b/Source/LibationAvalonia/ViewModels/MainVM.Import.cs index 3a021274..1c69294c 100644 --- a/Source/LibationAvalonia/ViewModels/MainVM.Import.cs +++ b/Source/LibationAvalonia/ViewModels/MainVM.Import.cs @@ -1,4 +1,4 @@ -using ApplicationServices; +using ApplicationServices; using AudibleUtilities; using Avalonia.Controls; using Avalonia.Input; @@ -252,17 +252,17 @@ public partial class MainVM } else if (AccountsCount == 1) { - importMenuItem.Items.Add(new NativeMenuItem { Header = "Scan Library", Command = ReactiveCommand.Create(ScanAccountAsync), Gesture = new KeyGesture(Key.S, KeyModifiers.Alt | KeyModifiers.Meta) }); + importMenuItem.Items.Add(new NativeMenuItem { Header = "Scan Library", Command = ReactiveCommand.Create(ScanAccountAsync), Gesture = new KeyGesture(Key.S, KeyGestureHelper.MenuModifier) }); importMenuItem.Items.Add(new NativeMenuItemSeparator()); - importMenuItem.Items.Add(new NativeMenuItem { Header = "Remove Library Books", Command = ReactiveCommand.Create(RemoveBooksAsync), Gesture = new KeyGesture(Key.R, KeyModifiers.Alt | KeyModifiers.Meta) }); + importMenuItem.Items.Add(new NativeMenuItem { Header = "Remove Library Books", Command = ReactiveCommand.Create(RemoveBooksAsync), Gesture = new KeyGesture(Key.R, KeyGestureHelper.MenuModifier) }); } else { - importMenuItem.Items.Add(new NativeMenuItem { Header = "Scan Library of All Accounts", Command = ReactiveCommand.Create(ScanAllAccountsAsync), Gesture = new KeyGesture(Key.S, KeyModifiers.Alt | KeyModifiers.Meta) }); - importMenuItem.Items.Add(new NativeMenuItem { Header = "Scan Library of Some Accounts", Command = ReactiveCommand.Create(ScanSomeAccountsAsync), Gesture = new KeyGesture(Key.S, KeyModifiers.Alt | KeyModifiers.Meta | KeyModifiers.Shift) }); + importMenuItem.Items.Add(new NativeMenuItem { Header = "Scan Library of All Accounts", Command = ReactiveCommand.Create(ScanAllAccountsAsync), Gesture = new KeyGesture(Key.S, KeyGestureHelper.MenuModifier) }); + importMenuItem.Items.Add(new NativeMenuItem { Header = "Scan Library of Some Accounts", Command = ReactiveCommand.Create(ScanSomeAccountsAsync), Gesture = new KeyGesture(Key.S, KeyGestureHelper.MenuModifier | KeyModifiers.Shift) }); importMenuItem.Items.Add(new NativeMenuItemSeparator()); - importMenuItem.Items.Add(new NativeMenuItem { Header = "Remove Books from All Accounts", Command = ReactiveCommand.Create(RemoveBooksAllAsync), Gesture = new KeyGesture(Key.R, KeyModifiers.Alt | KeyModifiers.Meta) }); - importMenuItem.Items.Add(new NativeMenuItem { Header = "Remove Books from Some Accounts", Command = ReactiveCommand.Create(RemoveBooksSomeAsync), Gesture = new KeyGesture(Key.R, KeyModifiers.Alt | KeyModifiers.Meta | KeyModifiers.Shift) }); + importMenuItem.Items.Add(new NativeMenuItem { Header = "Remove Books from All Accounts", Command = ReactiveCommand.Create(RemoveBooksAllAsync), Gesture = new KeyGesture(Key.R, KeyGestureHelper.MenuModifier) }); + importMenuItem.Items.Add(new NativeMenuItem { Header = "Remove Books from Some Accounts", Command = ReactiveCommand.Create(RemoveBooksSomeAsync), Gesture = new KeyGesture(Key.R, KeyGestureHelper.MenuModifier | KeyModifiers.Shift) }); } importMenuItem.Items.Add(new NativeMenuItemSeparator()); diff --git a/Source/LibationAvalonia/Views/MainWindow.axaml.cs b/Source/LibationAvalonia/Views/MainWindow.axaml.cs index f1cae936..e0fd589e 100644 --- a/Source/LibationAvalonia/Views/MainWindow.axaml.cs +++ b/Source/LibationAvalonia/Views/MainWindow.axaml.cs @@ -35,13 +35,13 @@ public partial class MainWindow : ReactiveWindow Opened += MainWindow_Opened; Closing += MainWindow_Closing; - KeyBindings.Add(new KeyBinding { Command = ReactiveCommand.Create(selectAndFocusSearchBox), Gesture = new KeyGesture(Key.F, Configuration.IsMacOs ? KeyModifiers.Meta : KeyModifiers.Control) }); + KeyBindings.Add(new KeyBinding { Command = ReactiveCommand.Create(selectAndFocusSearchBox), Gesture = new KeyGesture(Key.F, KeyGestureHelper.CommandModifier) }); if (!Configuration.IsMacOs && ViewModel is MainVM vm) { - KeyBindings.Add(new KeyBinding { Command = ReactiveCommand.Create(vm.ShowSettingsAsync), Gesture = new KeyGesture(Key.P, KeyModifiers.Control) }); - KeyBindings.Add(new KeyBinding { Command = ReactiveCommand.Create(vm.ShowAccountsAsync), Gesture = new KeyGesture(Key.A, KeyModifiers.Control | KeyModifiers.Shift) }); - KeyBindings.Add(new KeyBinding { Command = ReactiveCommand.Create(vm.ExportLibraryAsync), Gesture = new KeyGesture(Key.S, KeyModifiers.Control) }); + KeyBindings.Add(new KeyBinding { Command = ReactiveCommand.Create(vm.ShowSettingsAsync), Gesture = new KeyGesture(Key.P, KeyGestureHelper.CommandModifier) }); + KeyBindings.Add(new KeyBinding { Command = ReactiveCommand.Create(vm.ShowAccountsAsync), Gesture = new KeyGesture(Key.A, KeyGestureHelper.CommandModifier | KeyModifiers.Shift) }); + KeyBindings.Add(new KeyBinding { Command = ReactiveCommand.Create(vm.ExportLibraryAsync), Gesture = new KeyGesture(Key.S, KeyGestureHelper.CommandModifier) }); } Configuration.Instance.PropertyChanged += Settings_PropertyChanged;