Make messages selectable

This commit is contained in:
Stone_Red
2026-08-03 00:42:07 +02:00
parent b712ca6cc9
commit a4c245dbdc
5 changed files with 71 additions and 70 deletions
@@ -202,6 +202,11 @@ public sealed class MessageComposerViewModel : ViewModelBase
ReplyTarget = null;
}
public void UpdateAutocomplete(string text, int caretIndex)
{
Autocomplete.Update(text, caretIndex);
}
internal void Send()
{
string text = Draft.Trim();
@@ -230,9 +235,4 @@ public sealed class MessageComposerViewModel : ViewModelBase
? $"{StagedFiles.Count} file(s) staged"
: string.Empty;
}
public void UpdateAutocomplete(string text, int caretIndex)
{
Autocomplete.Update(text, caretIndex);
}
}
+4 -4
View File
@@ -50,10 +50,10 @@
Opacity="0.5"
IsVisible="{Binding HasReply}"
PointerPressed="OnReplyQuotePointerPressed" />
<TextBlock x:Name="MessageContent"
VerticalAlignment="Top"
TextWrapping="Wrap"
IsVisible="{Binding ShowContent}" />
<SelectableTextBlock x:Name="MessageContent"
VerticalAlignment="Top"
TextWrapping="Wrap"
IsVisible="{Binding ShowContent}" />
<ItemsControl ItemsSource="{Binding Attachments}"
IsVisible="{Binding HasAttachments}"
Margin="0 4 0 0">
+1 -1
View File
@@ -117,7 +117,7 @@ public partial class MessageItemView : UserControl
private void BuildMessageInlines(string content)
{
TextBlock? tb = MessageContent;
SelectableTextBlock? tb = MessageContent;
if (tb is null)
{
return;
+60 -59
View File
@@ -17,12 +17,72 @@ public partial class MessageListView : UserControl
private bool _loadingMore;
private double _loadingMoreExtent;
private MessageViewModel? _highlightedMessage;
private CancellationTokenSource? _highlightCts;
public MessageListView()
{
InitializeComponent();
DataContextChanged += OnDataContextChanged;
}
public void ScrollToMessage(string messageId)
{
if (_chat is null) return;
MessageViewModel? target = _chat.Messages.FirstOrDefault(m => m.Model.Id == messageId);
if (target is null) return;
ScrollViewer? scroll = this.FindControl<ScrollViewer>("MessageScrollViewer");
if (scroll is null) return;
ClearHighlight();
target.IsHighlighted = true;
_highlightedMessage = target;
_highlightCts = new CancellationTokenSource();
CancellationToken ct = _highlightCts.Token;
Dispatcher.UIThread.Post(() =>
{
double? targetY = FindItemY(scroll, target);
if (targetY is not null)
scroll.Offset = new Vector(scroll.Offset.X, targetY.Value);
}, DispatcherPriority.Render);
_ = Task.Run(async () =>
{
try
{
await Task.Delay(2000, ct);
Dispatcher.UIThread.Post(() =>
{
target.IsHighlighted = false;
if (_highlightedMessage == target)
_highlightedMessage = null;
});
}
catch (OperationCanceledException)
{
}
});
}
private static double? FindItemY(Visual parent, MessageViewModel target)
{
foreach (Visual child in parent.GetVisualChildren())
{
if (child.DataContext == target)
return child.Bounds.Y;
double? result = FindItemY(child, target);
if (result.HasValue)
return result;
}
return null;
}
private void OnDataContextChanged(object? sender, EventArgs args)
{
if (_chat is not null)
@@ -142,65 +202,6 @@ public partial class MessageListView : UserControl
Dispatcher.UIThread.Post(scroll.ScrollToEnd, DispatcherPriority.Background);
}
public void ScrollToMessage(string messageId)
{
if (_chat is null) return;
MessageViewModel? target = _chat.Messages.FirstOrDefault(m => m.Model.Id == messageId);
if (target is null) return;
ScrollViewer? scroll = this.FindControl<ScrollViewer>("MessageScrollViewer");
if (scroll is null) return;
ClearHighlight();
target.IsHighlighted = true;
_highlightedMessage = target;
_highlightCts = new CancellationTokenSource();
CancellationToken ct = _highlightCts.Token;
Dispatcher.UIThread.Post(() =>
{
double? targetY = FindItemY(scroll, target);
if (targetY is not null)
scroll.Offset = new Vector(scroll.Offset.X, targetY.Value);
}, DispatcherPriority.Render);
_ = Task.Run(async () =>
{
try
{
await Task.Delay(2000, ct);
Dispatcher.UIThread.Post(() =>
{
target.IsHighlighted = false;
if (_highlightedMessage == target)
_highlightedMessage = null;
});
}
catch (OperationCanceledException)
{
}
});
}
private static double? FindItemY(Visual parent, MessageViewModel target)
{
foreach (Visual child in parent.GetVisualChildren())
{
if (child.DataContext == target)
return child.Bounds.Y;
double? result = FindItemY(child, target);
if (result.HasValue)
return result;
}
return null;
}
private MessageViewModel? _highlightedMessage;
private CancellationTokenSource? _highlightCts;
private void ClearHighlight()
{
_highlightCts?.Cancel();