mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-02-12 13:01:37 +00:00
Fixed shortcut key monitoring
This commit is contained in:
parent
18fa36c32b
commit
7ff53ebcae
@ -12,44 +12,37 @@
|
||||
@T("Press the desired key combination to set the shortcut. The shortcut will be registered globally and will work even when the app is not focused.")
|
||||
</MudJustifiedText>
|
||||
|
||||
<MudPaper Class="pa-4 mb-3 d-flex align-center justify-center shortcut-capture-area"
|
||||
Style="min-height: 80px; cursor: pointer;"
|
||||
Elevation="2"
|
||||
@onclick="@this.FocusInput">
|
||||
@* Hidden input to capture keyboard events *@
|
||||
<input type="text"
|
||||
@ref="this.hiddenInput"
|
||||
@onkeydown="@this.HandleKeyDown"
|
||||
style="position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none;"
|
||||
autocomplete="off"
|
||||
readonly />
|
||||
@if (string.IsNullOrWhiteSpace(this.currentShortcut))
|
||||
{
|
||||
<MudText Typo="Typo.h6" Color="Color.Secondary">
|
||||
@T("Press a key combination...")
|
||||
</MudText>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.h5" Color="Color.Primary">
|
||||
@this.GetDisplayShortcut()
|
||||
</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
<MudFocusTrap DefaultFocus="DefaultFocus.FirstChild">
|
||||
<MudTextField
|
||||
@ref="@this.inputField"
|
||||
T="string"
|
||||
Text="@this.ShowText"
|
||||
Variant="Variant.Outlined"
|
||||
Label="@T("Define a shortcut")"
|
||||
Placeholder="@T("Press a key combination...")"
|
||||
Adornment="Adornment.Start"
|
||||
AdornmentIcon="@Icons.Material.Filled.Keyboard"
|
||||
Immediate="@true"
|
||||
TextUpdateSuppression="false"
|
||||
OnKeyDown="@this.HandleKeyDown"
|
||||
OnBlur="@this.HandleBlur"
|
||||
UserAttributes="@USER_INPUT_ATTRIBUTES"
|
||||
AutoFocus="true"
|
||||
KeyDownPreventDefault="true"
|
||||
KeyUpPreventDefault="true"
|
||||
HelperText="@T("Supported modifiers: Ctrl/Cmd, Shift, Alt.")"
|
||||
Class="me-3"/>
|
||||
</MudFocusTrap>
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(this.validationMessage))
|
||||
{
|
||||
<MudAlert Severity="@this.validationSeverity" Class="mb-3">
|
||||
<MudAlert Severity="@this.validationSeverity" Variant="Variant.Filled" Class="mb-3">
|
||||
@this.validationMessage
|
||||
</MudAlert>
|
||||
}
|
||||
|
||||
<MudText Typo="Typo.caption" Color="Color.Secondary" Class="mb-2">
|
||||
@T("Supported modifiers: Ctrl/Cmd, Shift, Alt. Example: Ctrl+Shift+R")
|
||||
</MudText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton OnClick="@this.ClearShortcut" Variant="Variant.Text" Color="Color.Warning" StartIcon="@Icons.Material.Filled.Clear">
|
||||
<MudButton OnClick="@this.ClearShortcut" Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Clear">
|
||||
@T("Clear Shortcut")
|
||||
</MudButton>
|
||||
<MudSpacer/>
|
||||
|
||||
@ -29,44 +29,42 @@ public partial class ShortcutDialog : MSGComponentBase
|
||||
[Parameter]
|
||||
public string ShortcutName { get; set; } = string.Empty;
|
||||
|
||||
private ElementReference hiddenInput;
|
||||
private static readonly Dictionary<string, object?> USER_INPUT_ATTRIBUTES = new();
|
||||
|
||||
private string currentShortcut = string.Empty;
|
||||
private string validationMessage = string.Empty;
|
||||
private Severity validationSeverity = Severity.Info;
|
||||
private bool hasValidationError;
|
||||
|
||||
// Current key state
|
||||
//
|
||||
// Current key state:
|
||||
//
|
||||
private bool hasCtrl;
|
||||
private bool hasShift;
|
||||
private bool hasAlt;
|
||||
private bool hasMeta;
|
||||
private string? currentKey;
|
||||
|
||||
private bool isFirstRender = true;
|
||||
private MudTextField<string>? inputField;
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override void OnInitialized()
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
base.OnInitialized();
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
// Configure the spellchecking for the user input:
|
||||
this.SettingsManager.InjectSpellchecking(USER_INPUT_ATTRIBUTES);
|
||||
|
||||
this.currentShortcut = this.InitialShortcut;
|
||||
this.ParseExistingShortcut();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
// Auto-focus the hidden input when the dialog opens
|
||||
if (this.isFirstRender)
|
||||
{
|
||||
this.isFirstRender = false;
|
||||
await this.hiddenInput.FocusAsync();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string ShowText => string.IsNullOrWhiteSpace(this.currentShortcut)
|
||||
? T("Press a key combination...")
|
||||
: this.GetDisplayShortcut();
|
||||
|
||||
private void ParseExistingShortcut()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(this.currentShortcut))
|
||||
@ -107,15 +105,9 @@ public partial class ShortcutDialog : MSGComponentBase
|
||||
}
|
||||
}
|
||||
|
||||
private async Task FocusInput()
|
||||
{
|
||||
// Focus the hidden input to capture keyboard events
|
||||
await this.hiddenInput.FocusAsync();
|
||||
}
|
||||
|
||||
private async Task HandleKeyDown(KeyboardEventArgs e)
|
||||
{
|
||||
// Ignore pure modifier key presses
|
||||
// Ignore pure modifier key presses:
|
||||
if (IsModifierKey(e.Code))
|
||||
{
|
||||
this.UpdateModifiers(e);
|
||||
@ -124,10 +116,9 @@ public partial class ShortcutDialog : MSGComponentBase
|
||||
return;
|
||||
}
|
||||
|
||||
// Update modifiers
|
||||
this.UpdateModifiers(e);
|
||||
|
||||
// Get the key
|
||||
// Get the key:
|
||||
this.currentKey = TranslateKeyCode(e.Code);
|
||||
|
||||
// Validate: must have at least one modifier + a key
|
||||
@ -140,11 +131,10 @@ public partial class ShortcutDialog : MSGComponentBase
|
||||
return;
|
||||
}
|
||||
|
||||
// Build the shortcut string
|
||||
this.UpdateShortcutString();
|
||||
|
||||
// Validate the shortcut
|
||||
await this.ValidateShortcut();
|
||||
|
||||
this.StateHasChanged();
|
||||
}
|
||||
|
||||
private void UpdateModifiers(KeyboardEventArgs e)
|
||||
@ -213,10 +203,7 @@ public partial class ShortcutDialog : MSGComponentBase
|
||||
|
||||
private string GetDisplayShortcut()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(this.currentShortcut))
|
||||
return string.Empty;
|
||||
|
||||
// Convert internal format to display format
|
||||
// Convert internal format to display format:
|
||||
return this.currentShortcut
|
||||
.Replace("CmdOrControl", OperatingSystem.IsMacOS() ? "Cmd" : "Ctrl")
|
||||
.Replace("CommandOrControl", OperatingSystem.IsMacOS() ? "Cmd" : "Ctrl");
|
||||
@ -376,4 +363,10 @@ public partial class ShortcutDialog : MSGComponentBase
|
||||
// Default: return as-is
|
||||
_ => code,
|
||||
};
|
||||
|
||||
private void HandleBlur()
|
||||
{
|
||||
// Re-focus the input field to keep capturing keys:
|
||||
this.inputField?.FocusAsync();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user