diff --git a/Source/LibationAvalonia/AccessKeyHandlerEx.cs b/Source/LibationAvalonia/AccessKeyHandlerEx.cs new file mode 100644 index 00000000..9369eb14 --- /dev/null +++ b/Source/LibationAvalonia/AccessKeyHandlerEx.cs @@ -0,0 +1,54 @@ +using Avalonia; +using Avalonia.Input; +using System.Linq; + +namespace LibationAvalonia +{ + internal class AccessKeyHandlerEx : AccessKeyHandler + { + public KeyModifiers KeyModifier { get; } + private readonly Key[] ActivatorKeys; + + public AccessKeyHandlerEx(KeyModifiers menuKeyModifier) + { + KeyModifier = menuKeyModifier; + ActivatorKeys = menuKeyModifier switch + { + KeyModifiers.Alt => new[] { Key.LeftAlt, Key.RightAlt }, + KeyModifiers.Control => new[] { Key.LeftCtrl, Key.RightCtrl }, + KeyModifiers.Meta => new[] { Key.LWin, Key.RWin }, + _ => throw new System.NotSupportedException($"{nameof(KeyModifiers)}.{menuKeyModifier} is not implemented"), + }; + } + + protected override void OnPreviewKeyDown(object sender, KeyEventArgs e) + { + if (ActivatorKeys.Contains(e.Key) && e.KeyModifiers.HasAllFlags(KeyModifier)) + { + var newArgs = new KeyEventArgs { Key = Key.LeftAlt, Handled = e.Handled }; + base.OnPreviewKeyDown(sender, newArgs); + e.Handled = newArgs.Handled; + } + } + + protected override void OnPreviewKeyUp(object sender, KeyEventArgs e) + { + if (ActivatorKeys.Contains(e.Key) && e.KeyModifiers.HasAllFlags(KeyModifier)) + { + var newArgs = new KeyEventArgs { Key = Key.LeftAlt, Handled = e.Handled }; + base.OnPreviewKeyUp(sender, newArgs); + e.Handled = newArgs.Handled; + } + } + + protected override void OnKeyDown(object sender, KeyEventArgs e) + { + if (e.KeyModifiers.HasAllFlags(KeyModifier)) + { + var newArgs = new KeyEventArgs { Key = e.Key, Handled = e.Handled, KeyModifiers = KeyModifiers.Alt }; + base.OnKeyDown(sender, newArgs); + e.Handled = newArgs.Handled; + } + } + } +} diff --git a/Source/LibationAvalonia/App.axaml.cs b/Source/LibationAvalonia/App.axaml.cs index e31714b4..c5e309ea 100644 --- a/Source/LibationAvalonia/App.axaml.cs +++ b/Source/LibationAvalonia/App.axaml.cs @@ -2,6 +2,7 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Input; using Avalonia.Markup.Xaml; using Avalonia.Media; using Avalonia.Platform; @@ -44,6 +45,9 @@ namespace LibationAvalonia { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { + var acceleratorKey = Configuration.IsMacOs ? KeyModifiers.Meta : KeyModifiers.Alt; + AvaloniaLocator.CurrentMutable.Bind().ToFunc(() => new AccessKeyHandlerEx(acceleratorKey)); + var config = Configuration.Instance; if (!config.LibationSettingsAreValid) diff --git a/Source/LibationAvalonia/Dialogs/Login/ApprovalNeededDialog.axaml b/Source/LibationAvalonia/Dialogs/Login/ApprovalNeededDialog.axaml index b092792e..10cde367 100644 --- a/Source/LibationAvalonia/Dialogs/Login/ApprovalNeededDialog.axaml +++ b/Source/LibationAvalonia/Dialogs/Login/ApprovalNeededDialog.axaml @@ -2,9 +2,10 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - mc:Ignorable="d" d:DesignWidth="240" d:DesignHeight="120" - MinWidth="240" MinHeight="120" - MaxWidth="240" MaxHeight="120" + mc:Ignorable="d" d:DesignWidth="240" d:DesignHeight="140" + MinWidth="240" MinHeight="140" + MaxWidth="240" MaxHeight="140" + Width="240" Height="140" x:Class="LibationAvalonia.Dialogs.Login.ApprovalNeededDialog" Title="Approval Alert Detected" Icon="/Assets/libation.ico"> diff --git a/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs b/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs index 48bbe611..143b31ca 100644 --- a/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs +++ b/Source/LibationAvalonia/Dialogs/Login/AvaloniaLoginChoiceEager.cs @@ -25,7 +25,8 @@ namespace LibationAvalonia.Dialogs.Login { var dialog = new LoginChoiceEagerDialog(_account); - if (await dialog.ShowDialogAsync() is not DialogResult.OK || string.IsNullOrWhiteSpace(dialog.Password)) + if (await dialog.ShowDialogAsync() is not DialogResult.OK || + (dialog.LoginMethod is LoginMethod.Api && string.IsNullOrWhiteSpace(dialog.Password))) return null; switch (dialog.LoginMethod) diff --git a/Source/LibationAvalonia/Dialogs/Login/CaptchaDialog.axaml b/Source/LibationAvalonia/Dialogs/Login/CaptchaDialog.axaml index f87f7711..363d0f8c 100644 --- a/Source/LibationAvalonia/Dialogs/Login/CaptchaDialog.axaml +++ b/Source/LibationAvalonia/Dialogs/Login/CaptchaDialog.axaml @@ -5,6 +5,7 @@ mc:Ignorable="d" d:DesignWidth="220" d:DesignHeight="250" MinWidth="220" MinHeight="250" MaxWidth="220" MaxHeight="250" + Width="220" Height="250" x:Class="LibationAvalonia.Dialogs.Login.CaptchaDialog" Title="CAPTCHA" Icon="/Assets/libation.ico"> diff --git a/Source/LibationAvalonia/Dialogs/Login/MfaDialog.axaml b/Source/LibationAvalonia/Dialogs/Login/MfaDialog.axaml index 264f2d05..8be808a7 100644 --- a/Source/LibationAvalonia/Dialogs/Login/MfaDialog.axaml +++ b/Source/LibationAvalonia/Dialogs/Login/MfaDialog.axaml @@ -4,7 +4,8 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="200" MinWidth="400" MinHeight="200" - MaxWidth="400" MaxHeight="200" + MaxWidth="400" MaxHeight="400" + Width="400" Height="200" x:Class="LibationAvalonia.Dialogs.Login.MfaDialog" Title="Two-Step Verification" Icon="/Assets/libation.ico"> diff --git a/Source/LibationAvalonia/Dialogs/Login/_2faCodeDialog.axaml b/Source/LibationAvalonia/Dialogs/Login/_2faCodeDialog.axaml index ebf37603..064acfcd 100644 --- a/Source/LibationAvalonia/Dialogs/Login/_2faCodeDialog.axaml +++ b/Source/LibationAvalonia/Dialogs/Login/_2faCodeDialog.axaml @@ -5,6 +5,7 @@ mc:Ignorable="d" d:DesignWidth="200" d:DesignHeight="200" MinWidth="200" MinHeight="200" MaxWidth="200" MaxHeight="200" + Width="200" Height="200" x:Class="LibationAvalonia.Dialogs.Login._2faCodeDialog" Title="2FA Code" Icon="/Assets/libation.ico"> diff --git a/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs b/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs index df313002..062893dd 100644 --- a/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs +++ b/Source/LibationWinForms/Dialogs/Login/WinformLoginChoiceEager.cs @@ -25,7 +25,7 @@ namespace LibationWinForms.Login { using var dialog = new LoginChoiceEagerDialog(_account); - if (!ShowDialog(dialog) || string.IsNullOrWhiteSpace(dialog.Password)) + if (!ShowDialog(dialog) || (dialog.LoginMethod is LoginMethod.Api && string.IsNullOrWhiteSpace(dialog.Password))) return null; switch (dialog.LoginMethod)