mirror of
https://github.com/Stone-Red-Code/Decho.git
synced 2026-09-04 00:46:11 +02:00
Make messages selectable
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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">
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user