Improve email suggestion handling and keyboard navigation
Enhanced the email suggestion feature by adding keyboard navigation support (`ArrowUp`, `ArrowDown`, `Enter`, `Escape`) and introducing `_selectedReceiverEmailSuggestion` to track the current selection. Updated methods to synchronize input and suggestions, pre-select matching suggestions, and reset the state when the popup is opened or closed. Improved error handling and ensured clean state management for better user experience.
This commit is contained in:
@@ -281,12 +281,14 @@
|
||||
|
||||
<div class="sender-receiver-popup__field">
|
||||
<div class="sender-receiver-popup__label">E-Mail-Adresse</div>
|
||||
<div @onkeydown="OnReceiverEmailKeyDownAsync">
|
||||
<DxTextBox Text="@_receiverDraftEmail"
|
||||
TextChanged="OnReceiverEmailTextChangedAsync"
|
||||
NullText="name@beispiel.de"
|
||||
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto"
|
||||
BindValueMode="BindValueMode.OnInput"
|
||||
CssClass="w-100" />
|
||||
</div>
|
||||
|
||||
<div class="sender-receiver-popup__suggestions-shell">
|
||||
@if (_receiverEmailSuggestions.Count > 0)
|
||||
@@ -295,7 +297,7 @@
|
||||
<DxListBox TData="string"
|
||||
TValue="string"
|
||||
Data="@_receiverEmailSuggestions"
|
||||
Value="@_receiverDraftEmail"
|
||||
Value="@_selectedReceiverEmailSuggestion"
|
||||
ValueChanged="OnReceiverEmailSuggestionSelectedAsync"
|
||||
SelectionMode="ListBoxSelectionMode.Single"
|
||||
CssClass="w-100" />
|
||||
@@ -355,6 +357,7 @@
|
||||
bool _receiverPopupVisible;
|
||||
string _receiverDraftName = string.Empty;
|
||||
string _receiverDraftEmail = string.Empty;
|
||||
string? _selectedReceiverEmailSuggestion;
|
||||
string? _receiverPopupValidationMessage;
|
||||
bool _isReceiverEmailSearchRunning;
|
||||
List<string> _receiverEmailSuggestions = [];
|
||||
@@ -473,6 +476,7 @@
|
||||
{
|
||||
_receiverDraftName = string.Empty;
|
||||
_receiverDraftEmail = string.Empty;
|
||||
_selectedReceiverEmailSuggestion = null;
|
||||
_receiverPopupValidationMessage = null;
|
||||
_receiverEmailSuggestions.Clear();
|
||||
_receiverPopupVisible = true;
|
||||
@@ -482,6 +486,7 @@
|
||||
{
|
||||
_receiverPopupVisible = false;
|
||||
_receiverPopupValidationMessage = null;
|
||||
_selectedReceiverEmailSuggestion = null;
|
||||
_isReceiverEmailSearchRunning = false;
|
||||
}
|
||||
|
||||
@@ -491,12 +496,56 @@
|
||||
_receiverPopupValidationMessage = null;
|
||||
}
|
||||
|
||||
async Task OnReceiverEmailKeyDownAsync(KeyboardEventArgs e)
|
||||
{
|
||||
if (_receiverEmailSuggestions.Count == 0)
|
||||
{
|
||||
if (e.Key == "Escape")
|
||||
_selectedReceiverEmailSuggestion = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var currentIndex = _selectedReceiverEmailSuggestion is null
|
||||
? -1
|
||||
: _receiverEmailSuggestions.FindIndex(email => string.Equals(email, _selectedReceiverEmailSuggestion, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (e.Key == "ArrowDown")
|
||||
{
|
||||
var nextIndex = currentIndex < _receiverEmailSuggestions.Count - 1 ? currentIndex + 1 : 0;
|
||||
await OnReceiverEmailSuggestionSelectedAsync(_receiverEmailSuggestions[nextIndex]);
|
||||
}
|
||||
else if (e.Key == "ArrowUp")
|
||||
{
|
||||
var nextIndex = currentIndex > 0 ? currentIndex - 1 : _receiverEmailSuggestions.Count - 1;
|
||||
await OnReceiverEmailSuggestionSelectedAsync(_receiverEmailSuggestions[nextIndex]);
|
||||
}
|
||||
else if (e.Key == "Enter")
|
||||
{
|
||||
var selectedValue = currentIndex >= 0 && currentIndex < _receiverEmailSuggestions.Count
|
||||
? _receiverEmailSuggestions[currentIndex]
|
||||
: _receiverEmailSuggestions.FirstOrDefault();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(selectedValue))
|
||||
{
|
||||
await OnReceiverEmailSuggestionSelectedAsync(selectedValue);
|
||||
_receiverEmailSuggestions.Clear();
|
||||
}
|
||||
}
|
||||
else if (e.Key == "Escape")
|
||||
{
|
||||
_receiverEmailSuggestions.Clear();
|
||||
_selectedReceiverEmailSuggestion = null;
|
||||
}
|
||||
}
|
||||
|
||||
Task OnReceiverEmailSuggestionSelectedAsync(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return Task.CompletedTask;
|
||||
|
||||
_receiverDraftEmail = value.Trim();
|
||||
_selectedReceiverEmailSuggestion = value.Trim();
|
||||
_receiverDraftEmail = _selectedReceiverEmailSuggestion;
|
||||
_receiverPopupValidationMessage = null;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -504,6 +553,7 @@
|
||||
async Task OnReceiverEmailTextChangedAsync(string? value)
|
||||
{
|
||||
_receiverDraftEmail = value?.Trim() ?? string.Empty;
|
||||
_selectedReceiverEmailSuggestion = _receiverDraftEmail;
|
||||
_receiverPopupValidationMessage = null;
|
||||
|
||||
var searchVersion = ++_receiverEmailSearchVersion;
|
||||
@@ -511,6 +561,7 @@
|
||||
if (string.IsNullOrWhiteSpace(_receiverDraftEmail) || _receiverDraftEmail.Length < 2)
|
||||
{
|
||||
_receiverEmailSuggestions.Clear();
|
||||
_selectedReceiverEmailSuggestion = null;
|
||||
_isReceiverEmailSearchRunning = false;
|
||||
return;
|
||||
}
|
||||
@@ -530,12 +581,18 @@
|
||||
.OrderBy(email => email)
|
||||
.Take(12)
|
||||
.ToList();
|
||||
|
||||
_selectedReceiverEmailSuggestion = _receiverEmailSuggestions.FirstOrDefault(email =>
|
||||
string.Equals(email, _receiverDraftEmail, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Failed to load receiver email suggestions for {SearchTerm}", _receiverDraftEmail);
|
||||
if (searchVersion == _receiverEmailSearchVersion)
|
||||
{
|
||||
_receiverEmailSuggestions.Clear();
|
||||
_selectedReceiverEmailSuggestion = null;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user