mirror of
https://github.com/Stone-Red-Code/Decho.git
synced 2026-09-04 08:56:14 +02:00
Fix auto complete not working in middle of text
This commit is contained in:
@@ -31,7 +31,9 @@ public sealed class AutocompleteController(IEnumerable<AutocompleteProvider> pro
|
|||||||
|
|
||||||
public int TriggerCharIndex { get; private set; }
|
public int TriggerCharIndex { get; private set; }
|
||||||
|
|
||||||
public void Update(string text)
|
public int WordEndIndex { get; private set; }
|
||||||
|
|
||||||
|
public void Update(string text, int caretIndex)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(text) || _providers.Count == 0)
|
if (string.IsNullOrEmpty(text) || _providers.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -39,7 +41,8 @@ public sealed class AutocompleteController(IEnumerable<AutocompleteProvider> pro
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Match match = TriggerPattern.Match(text);
|
int clampedCaret = Math.Clamp(caretIndex, 0, text.Length);
|
||||||
|
Match match = TriggerPattern.Match(text[..clampedCaret]);
|
||||||
if (!match.Success)
|
if (!match.Success)
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
@@ -58,6 +61,7 @@ public sealed class AutocompleteController(IEnumerable<AutocompleteProvider> pro
|
|||||||
ActiveProvider = provider;
|
ActiveProvider = provider;
|
||||||
FilterText = filter;
|
FilterText = filter;
|
||||||
TriggerCharIndex = match.Index;
|
TriggerCharIndex = match.Index;
|
||||||
|
WordEndIndex = match.Index + match.Length;
|
||||||
|
|
||||||
List<string> items = provider.ItemsSource().ToList();
|
List<string> items = provider.ItemsSource().ToList();
|
||||||
List<string> filtered = items
|
List<string> filtered = items
|
||||||
|
|||||||
@@ -106,8 +106,6 @@ public sealed class MessageComposerViewModel : ViewModelBase
|
|||||||
(draft, hasFiles, isReadOnly) =>
|
(draft, hasFiles, isReadOnly) =>
|
||||||
(!string.IsNullOrWhiteSpace(draft) || hasFiles) && !isReadOnly);
|
(!string.IsNullOrWhiteSpace(draft) || hasFiles) && !isReadOnly);
|
||||||
SendCommand = ReactiveCommand.Create(Send, canSend);
|
SendCommand = ReactiveCommand.Create(Send, canSend);
|
||||||
|
|
||||||
_ = this.WhenAnyValue(x => x.Draft).Subscribe(OnDraftChanged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateAvailableUsers(IEnumerable<UserViewModel> users)
|
public void UpdateAvailableUsers(IEnumerable<UserViewModel> users)
|
||||||
@@ -179,17 +177,24 @@ public sealed class MessageComposerViewModel : ViewModelBase
|
|||||||
return _commandHandler?.IsCommand(input) ?? input.StartsWith('/');
|
return _commandHandler?.IsCommand(input) ?? input.StartsWith('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InsertAutocomplete(string item)
|
public int InsertAutocomplete(string item)
|
||||||
{
|
{
|
||||||
string? insertion = Autocomplete.GetInsertion(item);
|
string? insertion = Autocomplete.GetInsertion(item);
|
||||||
if (insertion is null)
|
if (insertion is null)
|
||||||
{
|
{
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
string before = Draft[..Autocomplete.TriggerCharIndex];
|
string before = Draft[..Autocomplete.TriggerCharIndex];
|
||||||
Draft = $"{before}{insertion}";
|
string after = Draft[Autocomplete.WordEndIndex..];
|
||||||
|
if (after.Length > 0 && char.IsWhiteSpace(after[0]))
|
||||||
|
{
|
||||||
|
insertion = insertion.TrimEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
Draft = $"{before}{insertion}{after}";
|
||||||
Autocomplete.Reset();
|
Autocomplete.Reset();
|
||||||
|
return before.Length + insertion.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearReplyTarget()
|
public void ClearReplyTarget()
|
||||||
@@ -226,8 +231,8 @@ public sealed class MessageComposerViewModel : ViewModelBase
|
|||||||
: string.Empty;
|
: string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDraftChanged(string? draft)
|
public void UpdateAutocomplete(string text, int caretIndex)
|
||||||
{
|
{
|
||||||
Autocomplete.Update(draft ?? string.Empty);
|
Autocomplete.Update(text, caretIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
@@ -29,6 +30,11 @@ public partial class MessageComposerView : UserControl
|
|||||||
// Intercept Enter before the TextBox processes it (AcceptsReturn=True would insert a newline)
|
// Intercept Enter before the TextBox processes it (AcceptsReturn=True would insert a newline)
|
||||||
MessageTextBox.AddHandler(InputElement.KeyDownEvent, OnTextBoxTunnelingKeyDown, RoutingStrategies.Tunnel);
|
MessageTextBox.AddHandler(InputElement.KeyDownEvent, OnTextBoxTunnelingKeyDown, RoutingStrategies.Tunnel);
|
||||||
|
|
||||||
|
MessageTextBox.GetObservable(TextBox.TextProperty)
|
||||||
|
.Subscribe(_ => UpdateAutocomplete(MessageTextBox.Text ?? string.Empty, MessageTextBox.CaretIndex));
|
||||||
|
MessageTextBox.GetObservable(TextBox.CaretIndexProperty)
|
||||||
|
.Subscribe(_ => UpdateAutocomplete(MessageTextBox.Text ?? string.Empty, MessageTextBox.CaretIndex));
|
||||||
|
|
||||||
_spellChecker = new TextBoxSpellChecker(SpellCheckerConfig.Create("en_GB"));
|
_spellChecker = new TextBoxSpellChecker(SpellCheckerConfig.Create("en_GB"));
|
||||||
_spellChecker.Initialize(MessageTextBox);
|
_spellChecker.Initialize(MessageTextBox);
|
||||||
}
|
}
|
||||||
@@ -47,6 +53,12 @@ public partial class MessageComposerView : UserControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateAutocomplete(string text, int caretIndex)
|
||||||
|
{
|
||||||
|
MessageComposerViewModel? vm = this.GetDataContext<MessageComposerViewModel>();
|
||||||
|
vm?.UpdateAutocomplete(text, caretIndex);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnTextBoxKeyDown(object? sender, KeyEventArgs e)
|
private void OnTextBoxKeyDown(object? sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
MessageComposerViewModel? vm = this.GetDataContext<MessageComposerViewModel>();
|
MessageComposerViewModel? vm = this.GetDataContext<MessageComposerViewModel>();
|
||||||
@@ -137,8 +149,11 @@ public partial class MessageComposerView : UserControl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.InsertAutocomplete(item);
|
int newCaret = vm.InsertAutocomplete(item);
|
||||||
MessageTextBox.CaretIndex = MessageTextBox.Text?.Length ?? 0;
|
if (newCaret >= 0)
|
||||||
|
{
|
||||||
|
MessageTextBox.CaretIndex = newCaret;
|
||||||
|
}
|
||||||
_ = MessageTextBox.Focus();
|
_ = MessageTextBox.Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user